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 }

 

posted @ 2013-05-08 14:54  诺小J  阅读(252)  评论(0编辑  收藏  举报