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;
}

 

相关文章:

  • 2021-06-14
  • 2021-10-12
  • 2022-02-13
  • 2022-12-23
  • 2021-11-20
  • 2021-09-10
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-09-30
  • 2021-08-31
  • 2021-10-24
  • 2021-12-10
  • 2022-12-23
  • 2021-10-30
相关资源
相似解决方案