问题:求a~b中不包含49的数的个数,0 < a、b < 2*10^9
#include<cstdio>
#include<cstring>
int a,b,shu[20],dp[20][2];//数组shu用于记录输入数字的每一位上的数字,
//dp[i][0]表示第i+1位不为4的有i位数字的符合要求的数字的个数
//dp[i][1]表示第i+1位为4的有i位数字的符合要求的数字的个数
int dfs(int digit,bool if4,bool limit)//digit表示位数,if4表示上一位是否等于4,limit表示上一位是否达到极限
{
if(digit==0)//digit为0只有一个结果
return 1;
if(!limit&&dp[digit][if4])//上一位没有达到极限可以使用记忆过的内容
return dp[digit][if4];
int count=0,max1=(limit?shu[digit]:9);//max1表示该位上所能取的最大数字
int i;
for(i=0;i<=max1;i++)
{
if(if4&&i==9)//不满足条件直接跳过
continue;
count+=dfs(digit-1,i==4,limit&&i==max1);//记录满足条件的个数
}
return limit?count:dp[digit][if4]=count;//如果上一位达到极限,就不能记忆,因为个数不完整
}
int solve(int x)//该函数用于计算从0~x的符合要求的数的个数
{
memset(shu,0,sizeof(shu));//每次都得将数组shu初始化
int k=0;
while(x)//记录数字x每一位上的数字
{
shu[++k]=x%10;
x/=10;
}
return dfs(k,false,true);
}
int main()
{
scanf("%d%d",&a,&b);
printf("%d",solve(b)-solve(a-1));//答案等于从0~b的符合要求的数的个数减去从0~a-1的符合要求的数的个数
return 0;
}
问题:求a~b中不包含62和4的数的个数. 0 < a、b < 2*10^9
#include<cstdio>
#include<cstring>
int a,b,shu[20],dp[20][2];
int dfs(int digit,bool if6,bool limit)
{
if(digit==0)
return 1;
if(!limit&&dp[digit][if6])
return dp[digit][if6];
int count=0,max1=(limit?shu[digit]:9);
for(int i=0;i<=max1;i++)
{
if(i==4||if6&&i==2)
continue;
count+=dfs(digit-1,i==6,limit&&i==max1);
}
return limit?count:dp[digit][if6]=count;
}
int solve(int x)
{
memset(shu,0,sizeof(shu));
int k=0;
while(x)
{
shu[++k]=x%10;
x/=10;
}
return dfs(k,false,true);
}
int main()
{
scanf("%d%d",&a,&b);
printf("%d",solve(b)-solve(a-1));
return 0;
}
问题:找出1~n范围内含有13并且能被13整除的数字的个数
#include<cstdio>
#include<cstring>
int a,shu[20],dp[20][20][3];//dp[i][j][k]中i表示位数,j表示余数,k表示状态
int dfs(int digit,int mod,int state,bool limit)//mod表示余数,求余满足以下规律:
//(a*b)%mod=(a%mod)*(b%mod)
//(a+b)%mod=(a%mod)+(b%mod)
{
if(digit==0)
return mod==0&&state==2;
if(!limit&&dp[digit][mod][state])
return dp[digit][mod][state];
int cnt=0,max1=(limit?shu[digit]:9);
for(int i=0;i<=max1;i++)
{
int b=state;
if(state!=2&&i!=1)//state=0表示之前的数字中没有13,当前数字不是1
b=0;
if(state!=2&&i==1)//state=1表示之前的数字中没有13,当前数字是1
b=1;
if(state==1&&i==3)//state=2表示上个数字是1,当前数字是3
b=2; //state为2之后就不会在更改,表示已经达到条件
cnt+=dfs(digit-1,(mod*10+i)%13,b,limit&&i==max1);
} //余数*10再加上当前数字再做除法是除法的运算法则
return limit?cnt:dp[digit][mod][state]=cnt;
}
int main()
{
while(~scanf("%d",&a))
{
memset(shu,0,sizeof(shu));
memset(dp,0,sizeof(dp));
int k=0;
while(a)
{
shu[++k]=a%10;
a/=10;
}
printf("%d\n",dfs(k,0,0,1));
}
return 0;
}