解题思路:
dp[i][0]表示未出现吉利数,以2为首的i位数字有多少
dp[i][1]表示未出现吉利数,不以2和4为首的i位数字有多少
dp[i][2]表示出现吉利数的i位数字有多少
注意一下,2前面的数字为6的要排除掉就行
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int dp[10][3]; 6 void init(){ 7 memset(dp,0,sizeof dp); 8 dp[0][1]=1; 9 dp[1][0]=1,dp[1][1]=8,dp[1][2]=1; 10 for(int i=2;i<=6;i++){ 11 dp[i][0]=dp[i-1][0]+dp[i-1][1]; 12 dp[i][1]=dp[i-1][0]*7+dp[i-1][1]*8; 13 dp[i][2]=dp[i-1][0]*2+dp[i-1][1]+dp[i-1][2]*10; 14 } 15 } 16 int solve(int n){ 17 int ct=0,c[10]; 18 while(n) c[ct++]=n%10,n/=10; 19 int ret=0; 20 for(int i=ct-1;i>=0;i--){ 21 if(c[i]>=7) ret+=(c[i]-2)*(dp[i][0]+dp[i][1])+dp[i][1]; 22 else if(c[i]>=5) ret+=(c[i]-1)*(dp[i][0]+dp[i][1]); 23 else ret+=c[i]*(dp[i][0]+dp[i][1]); 24 if(i+1<ct&&c[i]>=3&&c[i+1]==6) ret-=(dp[i][0]+dp[i][1]); 25 if(c[i]==4) break; 26 if(i+1<ct&&c[i]==2&&c[i+1]==6) break; 27 } 28 return ret; 29 } 30 int main(){ 31 init(); 32 int n,m; 33 while(~scanf("%d%d",&n,&m)){ 34 if(n==0&&m==0) break; 35 cout<<solve(m+1)-solve(n)<<endl; 36 } 37 return 0; 38 }