题目大意:给出数字N(N<2^63-1),问在1-N之间有多少个包含序列49的数字
考察点:数位DP
思路分析:关于数位DP,这里有一篇比较好的文章http://blog.youkuaiyun.com/cmonkey_cfj/article/details/7798809
接下来是关于这道题,我们用f[i][0]表示所有i位的数中不含49的个数,f[i][1]表示不含49,但是头是9的数,f[i][2]表示含49的个数。
那么我们可以得到以下三个状态转移方程:
f[i][0]=f[i-1][0]*10-f[i-1][1];
f[i][1]=f[i-1][0];
f[i][2]=f[i-1][1]+f[i-1][2]*10;
接下来就是对于具体的n的操作,枚举n的每一位算就行了。特殊情况就是可能n中已经有了49,那么这个时候把全部都加进来就行
#include<stdio.h>
unsigned long long f[25][3];
int a[25];
int len;
int main()
{
int t,i,flag,last;
unsigned long long n,ans;
memset(f,0,sizeof(f));
f[0][0]=1;
for (i=1;i<25;i++)
{
f[i][0]=f[i-1][0]*10-f[i-1][1];
f[i][1]=f[i-1][0];
f[i][2]=f[i-1][1]+f[i-1][2]*10;
}
scanf("%d",&t);
while (t--)
{
scanf("%I64d",&n);
len=0;n++;
memset(a,0,sizeof(a));
while (n>0)
{
len++;
a[len]=n%10;
n=n/10;
}
ans=0;flag=0;last=0;
for (i=len;i>0;i--)
{
ans=ans+a[i]*f[i-1][2];
if (flag==1)
ans=ans+f[i-1][0]*a[i];
if ((flag==0)&&(a[i]>4))
ans=ans+f[i-1][1];
if ((last==4)&&(a[i]==9))
flag=1;
last=a[i];
}
printf("%I64d\n",ans);
}
return 0;
}