题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555
题目大意:统计区间[1,n](n<2^63)内含有“49”的数的个数。
分析:我们可以先统计区间[1,n]内不含49的数的个数,然后拿n减去即可。
实现代码如下:
//数位DP,统计区间[n,m]内含有49的数的个数
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
ll f[25][10];
void init()
{
memset(f,0,sizeof(f));
f[0][0]=1;
for(int i=1;i<=22;i++) //1到7位数
for(int j=0;j<=9;j++) //第i位由0到9
for(int k=0;k<=9;k++) //第i+1位
if( !(j==4&&k==9) )
f[i][j]+=f[i-1][k];
}
int dig[25],len; //从右到左纪录x的每一位
void change(ll x)
{
len=1;
while(x)
{
dig[len++]=x%10;
x/=10;
}
dig[len]=0;
}
ll solve(ll x)
{
ll ans=0;
change(x);
for(int i=len;i>=0;i--)
{
for(int k=0;k<dig[i];k++)
if( !(k==9&&dig[i+1]==4) )
ans+=f[i][k];
if(dig[i]==9&&dig[i+1]==4)
break;
}
return ans;
}
int main()
{
init();
int t;
ll n;
scanf("%d",&t);
while(t--)
{
scanf("%I64d",&n);
printf("%I64d\n",n+1-solve(n+1));
}
return 0;
}