AcWing 1084. 数字游戏 II
原题链接
中等
作者:
Anoxia_3
,
2021-05-01 12:55:54
,
所有人可见
,
阅读 436
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int N = 12;
int P , l , r;
int f[N][N][110];//f[i][j][k]表示:共i位,且最高位是j的数字中,各个位数的和模n为k的数的个数
int mod(int a , int b)
{
return (a % b + b) % b;
}
void init()
{
memset(f , 0 , sizeof f);
for(int i = 0 ; i < 10 ; i++) f[1][i][i % P]++;
for(int i = 2 ; i < N ; i++) //枚举数字的位数
for(int j = 0 ; j < 10 ; j++) //最高位数字位j
for(int k = 0 ; k < P ; k++)//各个位上的数之和对P取模后的值
for(int p = 0 ; p < 10 ; p++)//枚举i-1位数字,且最高位是p
f[i][j][k] += f[i - 1][p][mod(k - j , P)];
//记i-1位数字各个位上的数字和为x,则(j + x) % P = k % P => x % P = (k - j) % P
}
int dp(int n)//[0,n]中,符合要求数的个数
{
if(!n) return 1;
vector<int> nums;
while(n) nums.push_back(n % 10) , n /= 10;
int res = 0;
int last = 0;//第i位之前的各个位置上的数的和
for(int i = nums.size() - 1 ; i >= 0 ; i--)
{
int x = nums[i];
for(int j = 0 ; j < x ; j++)
res += f[i + 1][j][mod(-last , P)];//剩下的i+1位数字的和对P取模的值加上last对P取模要是0
last += x;
if(!i) res += (last % P == 0);//别忘记加上最右分支的情况
}
return res;
}
int main()
{
while(cin >> l >> r >> P)
{
init();
cout << dp(r) - dp(l - 1) << endl;
}
}