[20200801NOIP提高组模拟T3]老司机

description

今有一数,名之曰(n).(n)范围者,([1,20])也.又有一长为(n)的序列(a),(a_{i}in[1,50]),先请你构造一新序列,使在其上取若干个数(同一位置的数只能取一次),相加能求出序列(a)中任意一数.请你求出最小的新序列长(k),并输出使序列长最小时字典序最小的合法序列.

solution

世纪大暴力.由大眼观察法可知,序列({1,2,4,8,16,32})必为合法序列, 所以(k)值最大只能为(6),接下来六层循环暴力求序列判断即可.

code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#define R register
#define next kdjadskfj
#define debug puts("mlg")
#define mod 1000000007
#define Mod(x) ((x%mod+mod)%mod)
using namespace std;
ll n;
ll num[1000];
ll ans[7];
ll h;
bool vis[51];
inline bool check(){
	vis[0]=true;
	for(R ll i=1;i<=50;i++) vis[i]=false;
	for(R ll i=h;i<=6;i++){
		for(R ll j=50-ans[i];j>=0;j--){
			if(vis[j]) vis[j+ans[i]]=true;
		}
	}
	for(R ll i=1;i<=n;i++) if(!vis[num[i]]) return false;
	return true;
}
int main(){
	freopen("driver.in","r",stdin);
	freopen("driver.out","w",stdout);
	n=read();
	for(R ll i=1;i<=n;i++){
		num[i]=read();
	}
	for(ans[1]=0;ans[1]<=50;++ans[1]){
		for(ans[2]=ans[1];ans[2]<=50;++ans[2]){
			for(ans[3]=ans[2];ans[3]<=50;++ans[3]){
				for(ans[4]=ans[3];ans[4]<=50;++ans[4]){
					for(ans[5]=ans[4];ans[5]<=50;++ans[5]){
						for(ans[6]=ans[5];ans[6]<=50;++ans[6]){
							h=0;
							while(ans[h]==0) ++h;
							if(check()){
								writeln(6-h+1);
								for(;h<=6;h++) writesp(ans[h]);
								return 0;
							}																				
						}
					}
				}
			}
		}
	}
}
原文地址:https://www.cnblogs.com/ylwtsq/p/13414624.html