数字游戏2
思路:
本题预处理比较复杂
fijk表示第i位上是j,并且余数是k的数字的个数
可以由i-1的状态转移过来
思考:为什么要存下余数的状态,这是因为,我们要去算modN为0的数字的时候要去算出前缀,如果前缀和后面的数总和modN为0,那么就是我们要求的方案数。
注意,以后遇到mod的方案数的时候都可以采用这样的方式去做。
代码:
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int N = 15,M = 105;
int f[N][N][M];
int p;
int mod(int x,int y){
return (x%y+y)%y;
}
void init()
{
memset(f,0,sizeof f);
for(int i = 0;i<=9;i++) f[1][i][i%p]++;
for(int i = 2;i<N;i++){
for(int j = 0;j<=9;j++){
for(int k = 0;k<p;k++){
for(int x = 0;x<=9;x++)
f[i][j][k]+=f[i-1][x][mod(k-j,p)];
}
}
}
}
int dp(int n){
if(!n) return 1;
vector<int> nums;
while (n){
nums.push_back(n%10);
n/=10;
}
int res = 0;
int last = 0;//存的是前缀的信息
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)];
last += x;
if(!i&&last%p==0)
res++;
}
return res;
}
int main() {
int l,r;
while (cin>>l>>r>>p){
init();
cout<<dp(r)-dp(l-1)<<endl;
}
return 0;
}