学习波罗的海小哥的做法,复杂度好虚:http://www.boi2014.lmio.lt/tasks.html
APIO2016 的 practise
据说是KlogK的
还有O(K)的做法
UPD:复杂度是有依据的 突然就脑补出来了 不过这个log是以10为底的
#include<cstdio>
#include<cstdlib>
#include<vector>
using namespace std;
typedef long long ll;
const ll NIL=102345678900000LL;
const int MAX_K=100000;
struct Set{
int bit;
Set() { bit=0; }
Set(int x) { bit=1<<x; }
bool empty(){ return !bit; }
bool count(int x){ return bit&(1<<x); }
void insert(int x){ bit|=1<<x; }
void erase(int x){ if (count(x)) bit-=1<<x; }
void insert(Set x){ bit|=x.bit; }
void clear(){ bit=0; }
ll Num(){
if (bit==1) return 10;
ll ret=0; int flag=0;
for (int i=1;i<=9;i++)
if (count(i))
{
ret=ret*10+i;
if (count(0) && !flag)
flag=1,ret*=10;
}
return ret;
}
void print(){
for (int i=0;i<=9;i++) if (count(i)) printf("%d ",i); printf("\n");
}
};
int K;
int B[MAX_K];
ll find(vector<Set> sets,bool Fini) {
int from=0,to=9;
if (sets.size()==1){
if (sets[0].empty()){
if (Fini) return 0;
from=1;
}
else
return sets[0].Num();
}
else if (sets.size()==2){
if (!sets[0].count(9) && !sets[1].count(0))
to=8;
}
ll ans=NIL;
for (int i=from;i<=to;i++){
vector<Set> New; Set cur,tmp;
bool fini=!(i==0 && (sets[0].count(0) || !Fini));
for (int j=0,t=i;j<(int)sets.size();j++,t++){
if (t==10)
t=0,New.push_back(cur),cur.clear();
tmp=sets[j]; tmp.erase(t);
cur.insert(tmp);
}
New.push_back(cur);
ll ret=find(New,fini);
if (ret!=NIL && (ans==NIL || ret*10+i<ans))
ans=ret*10+i;
}
return ans;
}
ll Solve(){
vector<Set> sets;
for (int i=0;i<K;i++)
sets.push_back(Set(B[i]));
ll ans=find(sets,1);
if (!ans) ans=10;
return ans;
}
int main() {
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
scanf("%d",&K);
for (int i=0;i<K;i++)
scanf("%d",&B[i]);
printf("%lld\n",Solve());
return 0;
}