首先應該初始化,分爲dp[i][0]dp[i][1]dp[i][2],分別表示不含有49的,不含49但最高位是9的,含有49的,遞推關係是dp[i][0]=dp[i-1][0]*10-dp[i-1][1];dp[i][1]=dp[i-1][0];dp[i][2]=dp[i-1][2]*10+dp[i-1][1];之後讀取數字,後從高位往下看,先加上有49的那部分,如果前面已經有49了那就再把不含49的那部分也加進去,如果前面不含49,但是現在查詢到的這個數大於4的話那就只加之後的以9開頭且不含49的數的個數,最後再判斷一下加了這個數是不是就可以包含49這個數了,要注意的是數據比較大,所以要用__int64型。
#include <stdio.h>
#include <cstring>
__int64 dp[20][3],a[20],l;
void init()
{
int i;
memset(dp,0,sizeof(dp));
dp[0][0]=1; //
for(i=1;i<20;i++)
{
dp[i][0]=(__int64)dp[i-1][0]*10-dp[i-1][1];
dp[i][1]=(__int64)dp[i-1][0];
dp[i][2]=(__int64)dp[i-1][2]*10+dp[i-1][1];
}
}
int main()
{
int i;
int t;
__int64 n;
init();
scanf("%d",&t);
while(t--)
{
memset(a,0,sizeof(a));
__int64 ans=0;
l=1;
int flag=0;
scanf("%I64d",&n);
n++; //應當注意到不加這一項的話,例如n=49時就無法取到正確的解,感覺原因像
//是因爲做if(!flag&&a[i]>4)判斷時把49這種可能性忽略了,加上去之後49自
//然就行了,而因爲這個進位的,由於進位後dp會自動加上dp[i-1][1],所以仍然成立
while(n)
{
a[l++]=n%10;
n=n/10;
}
for(i=l-1;i>=1;i--)
{
ans+=(__int64)dp[i-1][2]*a[i];
if(flag)
ans+=(__int64)dp[i-1][0]*a[i];
if(!flag&&a[i]>4)
ans+=(__int64)dp[i-1][1];
if(a[i]==9&&a[i+1]==4)
flag=1;
}
printf("%I64d\n",ans);
}
return 0;
}