ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

 序列A由从N开始的连续K个数按顺序构成,现在将A中的每个数只保留某一个数码,记为序列B,给定K和B,求可能的最小的N

Input

第一行一个数K,第二行K个数B_i

Output

输出一个数N

当确定了N的个位时,可以确定这连续的K个数的个位,这是得到子问题求N/10的值,B数组(压位表示子问题中哪些位必须出现)对应更新为大约K/10的长度,于是可以递归处理,当K=1时贪心确定所需的最高位

当K=2时若选择个位为9则递归下去K仍为2,要特判剪枝一下

递归到K=1时,若答案有必须存在的前导0则要特判在前面补位

#include<cstdio>
typedef long long i64;
int _(){
    int x=0,c=getchar();
    while(c<48)c=getchar();
    while(c>47)x=x*10+c-48,c=getchar();
    return x;
}
int n,v[100007],d[500007];
i64 dfs(int*d0,int n,bool _9,bool _0){
    bool dd=0;
    for(int i=0;i<n;++i)if(d0[i]){dd=1;break;}
    if(!dd)return _0;
    if(n==1){
        int x=*d0;
        if(x==1)x=3;
        i64 v=0;
        for(int i=1;i<10;++i)if(x>>i&1){
            v=i;
            x^=1<<i;
            break;
        }
        for(int i=0;i<10;++i)if(x>>i&1)v=v*10+i;
        return v;
    }
    i64 v0=1ll<<60;
    int*d1=d0+n;
    for(int a=0;a<10;++a){
        if(a==9&&!_9)break;
        int n1=0,x=a,s=0;
        for(int b=0;b<n;++b){
            s|=d0[b]&~(1<<x);
            if(++x==10){
                x=0;
                d1[n1++]=s;
                s=0;
            }
        }
        if(x)d1[n1++]=s;
        i64 v1=dfs(d1,n1,a!=9||n>2,!a&&(_0||(1&*d0)))*10+a;
        if(v1<v0)v0=v1;
    }
    return v0;
}
int main(){
    n=_();
    for(int i=0;i<n;++i)d[i]=1<<(v[i]=_());
    printf("%lld",dfs(d,n,1,1));
    return 0;
}

 

posted on 2016-11-14 20:06  nul  阅读(385)  评论(0编辑  收藏  举报