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