判斷(0,n]之間含49的數的個數
具體做法是數位DP , 用3個DP數組分別記錄第i位
dp0[i];//不含49的數的個數
dp1[i];//不含49,但第一位是9的個數
dp2[i];//含49個數
則由狀態轉移方程
dp0[i+1]=dp0[i]*10-dp1[i];
dp1[i+1]=dp0[i];
dp2[i+1]=dp1[i]+dp2[i]*10;
初始為1 0 0 就可以
之後處理個數,按字串讀入之後按位處理,每次遞加比該數位小的應有的數,所有如果n本身就是含49的話,就要再+1。
#include <cstdio>#include <cstring>typedef long long ll;const int maxn=25;ll dp0[maxn];//不含49ll dp1[maxn];//不含49,但第一位是9的ll dp2[maxn];//含49void init (){ dp0[0]=1; dp1[0]=0; dp2[0]=0; for (int i=0 ; i<20 ; ++i) { dp0[i+1]=dp0[i]*10-dp1[i]; dp1[i+1]=dp0[i]; dp2[i+1]=dp1[i]+dp2[i]*10;// dp2[i]*10表示dp2[i]*9+dp2[i]好理解些 //printf("%lld %lld %lld %lld\n",dp0[i],dp1[i],dp2[i],dp0[i]+dp2[i]); }}int main (){ init (); char str[25]; int num[25]; int cas ; scanf("%d",&cas); while (cas--) { scanf("%s",str); int len = strlen (str); for (int i=0 ; i<len ; ++i) num[i]=str[i]-48; ll cnt=num[0]*dp2[len-1]; //printf("%lld\n",cnt); if(num[0]>4) cnt+=dp1[len-1]; //printf("%lld\n",cnt); bool flag=0; for (int i=1 ; i<len ; ++i) { cnt+=num[i]*dp2[len-i-1]; //printf("%lld\t",cnt); if(flag)cnt+=num[i]*dp0[len-i-1]; if(!flag) if(num[i]>4) cnt+=dp1[len-i-1]; //printf("%lld\n",cnt); if(!flag)if(num[i-1]==4 && num[i]==9)flag=1; } for (int i=0 ; i<len-1 ; ++i) if(num[i]==4 && num[i+1]==9)flag=1; if(flag)cnt++; printf("%I64d\n",cnt); } return 0;}