hdu 2089 数位dp
说实在的,有点惭愧,这题,本来想用更好的办法,但是时间复杂度更高了。
朴素的办法就是打表,从1-1000000打一个统计1-n中的合格数的表。
递归枚举其中的数字:
View Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 using namespace std; 6 int const N = 20; 7 int l,r,n,m,num,sl[N],sr[N]; 8 int pow10[8],sl2[N],sr2[N]; 9 int getsum1(int i,int pre,int f) 10 { 11 if(i==0)return 0; 12 int ans=0,up; 13 if(f)up=sl[i]; 14 else up=10; 15 for(int j=0;j<up;j++) 16 { 17 if(j==4||(j==2&&pre==6)) 18 ans+=pow10[i-1]; 19 else 20 ans+=getsum1(i-1,j,0); 21 } 22 if(f) 23 { 24 if(sl[i]==4||(sl[i]==2&&pre==6))ans+=(1+sl2[i-1]); 25 else ans+=getsum1(i-1,sl[i],1); 26 } 27 return ans; 28 } 29 int getsum2(int i,int pre,int f) 30 { 31 if(i==0)return 0; 32 int ans=0,up; 33 if(f)up=sr[i]; 34 else up=10; 35 for(int j=0;j<up;j++) 36 { 37 if(j==4||(j==2&&pre==6)) 38 ans+=pow10[i-1]; 39 else 40 ans+=getsum2(i-1,j,0); 41 } 42 if(f) 43 { 44 if(sr[i]==4||(sr[i]==2&&pre==6))ans+=(1+sr2[i-1]); 45 else ans+=getsum2(i-1,sr[i],1); 46 } 47 return ans; 48 } 49 void pre() 50 { 51 pow10[0]=1; 52 for(int i=1;i<=7;i++)pow10[i]=pow10[i-1]*10; 53 } 54 int main() 55 { 56 pre(); 57 while(~scanf("%d %d",&l,&r)&&(l+r)!=0) 58 { 59 l--; 60 n=m=0; 61 num=l; 62 for(;num;num/=10)sl[++n]=num%10; 63 sl2[0]=0; 64 for(int i=1;i<=n;i++)sl2[i]=pow10[i-1]*sl[i]+sl2[i-1]; 65 num=r; 66 for(;num;num/=10)sr[++m]=num%10; 67 sr2[0]=0; 68 for(int i=1;i<=m;i++)sr2[i]=pow10[i-1]*sr[i]+sr2[i-1]; 69 printf("%d\n",(r-l)-getsum2(m,0,1)+getsum1(n,0,1)); 70 } 71 return 0; 72 }
最神的还是这位仁兄,看了他的代码,折服了(可以先看看这位牛的)