[暴力] BZOJ 3917 [Baltic2014]sequence

学习波罗的海小哥的做法,复杂度好虚: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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值