poj 3208 找出第n个包含666连续字串的数字
说白了,只要求出1-x中出现666子串的数字,然后二分枚举答案。
View Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 typedef long long LL; 6 int const N = 20; 7 LL dp1[N][N][N],dp2[N][N][N]; 8 int bit[N],ln; 9 LL getsum1(int t,int pre,int last,int flag,int limit) 10 { 11 if(!t)return flag; 12 int up=(limit?bit[t]:9); 13 LL ans=0; 14 if(!limit&&flag&&dp1[t][pre][last]!=-1)return dp1[t][pre][last]; 15 if(!limit&&!flag&&dp2[t][pre][last]!=-1)return dp2[t][pre][last]; 16 for(int i=0;i<=up;i++) 17 { 18 int f=0; 19 if(flag||(pre==6&&last==6&&i==6))f=1; 20 ans+=getsum1(t-1,last,i,f,limit&&i==up); 21 } 22 if(!limit&&flag&&dp1[t][pre][last]==-1)dp1[t][pre][last]=ans; 23 if(!limit&&!flag&&dp2[t][pre][last]==-1)dp2[t][pre][last]=ans; 24 return ans; 25 } 26 LL getsum2(LL n) 27 { 28 for(ln=0;n;bit[++ln]=n%10,n/=10); 29 return getsum1(ln,0,0,0,1); 30 } 31 int main() 32 { 33 int T; 34 scanf("%d",&T); 35 LL l,r,n,ans,mid; 36 memset(dp1,-1,sizeof(dp1)); 37 memset(dp2,-1,sizeof(dp2)); 38 while(T--) 39 { 40 scanf("%I64d",&n); 41 l=666LL,r=66600000000LL; 42 while(l<r) 43 { 44 mid=(l+r)>>1; 45 LL x=getsum2(mid); 46 if(x>=n) 47 r=mid; 48 else 49 l=mid+1; 50 } 51 printf("%I64d\n",l); 52 } 53 return 0; 54 }