2018农大校赛(折半查找)

题目链接

c(n,0)加到c(n,n)的和为2的n次方。

刚开始暴力dfs所有的组合,结果超时,后来用折半查找过的,忘了判断取jie数组里面的数不能大于19,re了两次

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define ll long long
using namespace std;

void dis(int a[], int n){
	printf("总数为%d个\n",n); 
	for(int i = 0; i < n; i++) 	cout<<a[i]<<", ";
	cout<<endl<<"------------------"<<endl;		
}

const int mx = 0;
int n,k,le,mi,ri;
int visa[26],visb[26];
ll s,ans,a[26],b[26],num[26],jie[21];
vector<ll>va[26];
vector<ll>vb[26];
void da (){
	jie[1] = jie[0] = 1;
	for(int i = 2 ; i < 19;i++){
		jie[i] = jie[i-1] * i;
	} 
	return;
} 
void init(){
	ans = 0;
	memset(visa,0,sizeof(visa));
	memset(visb,0,sizeof(visb));
	for(int i = 0; i < 26; i++){
		va[i].clear();
		vb[i].clear();
	}
}
void dfs1(int ge, ll sum, int cor){
	/*if(sum > s)
		return;*/
	for(int i = cor; i < le; i++){
		if(!visa[i]){
			visa[i] = 1;
			if(sum+a[i] <= s){
				va[ge].push_back(sum+a[i]);
				dfs1(ge,sum+a[i],i);
			}
			
			if(ge < k && a[i] < 19 &&(sum+jie[a[i]]) <= s){
				va[ge+1].push_back(sum+jie[a[i]]);
				dfs1(ge+1,sum+jie[a[i]],i);
			}
			visa[i] = 0;
		}
	}
}

void dfs2(int ge, ll sum, int cor){
	/*if(sum > s)
		return;*/
	for(int i = cor; i < ri; i++){
		if(!visb[i]){
			visb[i] = 1;
			if(sum+b[i] <= s){
				vb[ge].push_back(sum+b[i]);
				dfs2(ge,sum+b[i],i);
			}
			
			if(ge < k && b[i] < 19 &&(sum+jie[b[i]]) <= s){
				vb[ge+1].push_back(sum+jie[b[i]]);
				dfs2(ge+1,sum+jie[b[i]],i);
			}
			visb[i] = 0;
		}
	}
}
int main(){
	da();                       //打表求阶乘 
	while(scanf("%d%d%lld",&n,&k,&s) != EOF){
		mi = n / 2;	
		for(int i = 0; i < n ;i++){
			scanf("%lld",num+i);
		}
		 
		le = ri = 0;
		for(int i = 0; i < mi; i++){
			a[le++] = num[i];
		}
		
		for(int i = mi; i < n; i++){
			b[ri++] = num[i];
		}
		
		init();    // ans已被初始化 
		dfs1(0,0,0);
		dfs2(0,0,0);
		
		for(int i = 0; i <= k; i++)
			sort(vb[i].begin(),vb[i].end());
		ll te;
		
		for(int i = 0; i <= k; i++)
			for(int j = 0; (i+j) <= k; j++){
				for(int k = 0; k<va[i].size();k++){
					te = s - va[i][k];
					ans+=(upper_bound(vb[j].begin(),vb[j].end(),te) - lower_bound(vb[j].begin(),vb[j].end(),te));	
				}
			}
		
		for(int i = 0; i <= k; i++)
			for(int k = 0; k<vb[i].size();k++)
			if(vb[i][k] == s)
				ans++;
		for(int i = 0; i <= k; i++)
			for(int k = 0; k<va[i].size();k++)
			if(va[i][k] == s)
				ans++;
				
		cout<<ans<<endl;
	}
	
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37325947/article/details/80048913
今日推荐