1 100 0 0
80
题解:数位DP
具体过程参见代码
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<iostream> using namespace std; int n,m,cnt,num[10]; int dp[12][12]; int sqr(int x,int y) { int t=1; if (y==0) return 1; for (int i=1;i<=y;i++) t=t*10; return t; } int sqr1(int x,int y) { int t=0; for (int i=1;i<=y;i++) t=t*10+9; return t; } void init() { dp[0][0]=1; for (int i=1;i<=7;i++) { dp[i][0]=9*dp[i-1][0]-dp[i-1][1]; //dp[i][0] 表示位数不超过i的数字中不含不吉利的数字个数 dp[i][1]=dp[i-1][0];//dp[i][1] 表示位数不超过i的数字中不含不吉利数字,且最高位为2的个数 dp[i][2]=sqr1(9,i)+1-dp[i][0];//dp[i][2] 表示位数不超过i的数字中含不吉利数字的个数 } } int solve(int x) { int ans=0,k=x; cnt=0; int tot=0; while (x) //把数字按位分解 { num[++tot]=x%10; x/=10; } bool f=false; num[0]=0; num[tot+1]=0; for (int i=tot;i>=1;i--) //计算的时候,把数拆分,例如43,拆成1-39,40-43来计算 { if (f) { continue; } if (num[i]<4) ans+=(num[i])*dp[i-1][2]; //当前位小于4,直接计算0-(num[i]-1) else if (num[i]>4) ans+=sqr(10,i-1)+(num[i]-1)*dp[i-1][2];//当前位可以是0-(num[i]-1),把4的情况单独提出来计算 ,sqr(10,i-1)就是计算当前位上4的个数 else { ans+=(num[i])*dp[i-1][2];//计算当前位是0-3的个数 ans+=k%sqr(10,i-1)+1;//计算当前位是4时,剩下的位置有多少中填法 f=true;//因为如果当前位是4,剩下的位置无论怎么填都是不合法的,打个标记,避免重复计算 } if (num[i+1]==6)//计算含62的情况 { if (num[i]>2) ans+=dp[i][1]; else if (num[i]==2) ans+=k%sqr(10,i-1)+1; } else if (num[i+1]>6) ans+=dp[i][1]; if (num[i+1]==6&&num[i]==2) //因为如果当前位是2,前一位是6,剩下的位置无论怎么填都是不合法的,打个标记,避免重复计算 f=true; } return ans; } int main() { init(); while(scanf("%d%d",&n,&m)) { if (!n&&!m) break; int t=m-n+1-solve(m)+solve(n-1); printf("%d\n",t); } }