HUD 2089 位数dp
/* 做的不多的位数dp 暴力的话 不知道多少组数据 会T 所以写dp 思路就和数学课本上那种“不超过xxx的x位偶数有几个” 这里可以类似的维护一个前缀和模样的东西(但又不同于前缀和) 状态:f[i][j] 表示以j开头的i位数符合条件的个数 (j可以是0) 然后可以已处理一下像是10000这种整的数 注意舍去不符合条件的 然后对于一个像123456这样不整的数 就从该高位逐位找 以此类推 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; int st,en,ans,data[10],l,f[10][10]; void ready() { f[0][0]=1; for(int i=1;i<=7;i++)//枚举位数 for(int j=0;j<=9;j++)//枚举第i为是什么 for(int k=0;k<=9;k++)//枚举第i-1为是什么 if((j==6&&k==2)||j==4||k==4)continue;//舍去 else f[i][j]+=f[i-1][k]; } void get_data(int x) { while(x>0) { data[++l]=x%10; x=x/10; } } int slove(int x) { ans=0;l=0; memset(data,0,sizeof(data)); get_data(x);//得到每一个数拆完是什么 for(int i=l;i>=1;i--) { for(int j=0;j<data[i];j++)//枚举第i位是什么 枚举到<data[i] if((j==2&&data[i+1]==6)||j==4)continue; else ans+=f[i][j]; if(data[i]==4||(data[i]==2&&data[i+1]==6))break;//往后找的一定包含这个4 或者62 就不用找了 } return ans; } int main() { //freopen("cin.in","r",stdin); //freopen("test.out","w",stdout); ready(); while(1) { scanf("%d%d",&st,&en); if(st==0&&en==0)break; printf("%d\n",slove(en+1)-slove(st)); } return 0; }