题目描述
由于科协里最近真的很流行数字游戏,某人又命名了一种取模数,这种数字必须满足各位数字之和 mod N为 0。现在大家又要玩游戏了,指定一个整数闭区间 [a,b],问这个区间内有多少个取模数。
输入格式
题目有多组测试数据。每组只含三个数字 a, b, N。
输出格式
对于每个测试数据输出一行,表示各位数字和 mod N 为 0 的数的个数。
样例
Input
1 19 9
Output
2
数据范围与提示
对于全部数据,1≤ a,b≤231-1,1≤N<100。
代码1
#include "stdio.h"
#include "algorithm"
#include "string.h"
using namespace std;
int p;
int dp[20][109];
int s[99];
int dfs(int l,int m,bool limit)
{
if(!l)
{
if(m==0)
return 1;
return 0;
}
if(!limit&&dp[l][m]!=-1)
return dp[l][m];
int shu=0,ans=0;
if(limit)//这儿看是否受限制,不受限制的话0~9随便取,否则0~s[l],如就算234:此时如果百位是2,那么十位受限制只能取0~3(就是取得数要小于等于234),但如果百位是1,那么十位不受限制,可以取0~9
shu=s[l];
else
shu=9;
for(int i=0; i<=shu; i++)
ans+=dfs(l-1,(m+i)%p,limit&&i==s[l]) ;
if(!limit)
dp[l][m]=ans;
return ans;
}
int qqq(int n)
{
int l=0;
while(n)
{
s[++l]=n%10;
n/=10;
}
return dfs(l,0,1);//分别对应:位数,模,取得值是否受限制
}
int main()
{
int a,b;
while(~scanf("%d%d%d",&a,&b,&p))
{
memset(dp,-1,sizeof(dp));//每次p值不一定一样
printf("%d\n",qqq(b)-qqq(a-1));
}
}
代码2
#include "stdio.h"
#include "algorithm"
#include "string.h"
using namespace std;
int p,s[14];
int dp[14][12][109];//
int mmod(int m)
{
return (m%p+p)%p;//防止dp数组的第三个括号里的值为负数
}
void init()
{
for(int i=0; i<=9; i++)
dp[1][i][i%p]++;//1:此时我们计算的数字为1位数,即长度为1,i是这位数的最高位为多少(如23,最高位为十位,即2),i%p相对于dp[1][i][i%p]来说,最高位为i的长度为1(个位数)对p取余为i%p
//如dp[2][4][9]的值是长度为2(2位数)最高位为4 对p取余为9的总数
for(int i=2; i<=11; i++)
for(int j=0; j<=9; j++)
for(int k=0; k<p; k++)
for(int jj=0; jj<=9; jj++)
dp[i][j][k]+=dp[i-1][jj][mmod(k-j)];
}
int qqq(int n)
{
if(n==0)
return 1;
int l=0;
while(n)
{
s[++l]=n%10;
n/=10;
}
int sum=0;
int d=0;
for(; l>0; l--)
{
int x=s[l];
for(int i=0; i<x; i++)
{
sum+=dp[l][i][mmod(0-d)];
}
d+=x;
if(l==1&&d%p==0)
sum++;
}
return sum;
}
int main()
{
int a,b;
while(~scanf("%d%d%d",&a,&b,&p))
{
memset(dp,0,sizeof(dp));
init();
printf("%d\n",qqq(b)-qqq(a-1));
}
}