codeforces 525 E Anya and Cubes 中途相遇法

codeforces 525 E Anya and Cubes 中途相遇法
题意:
给出n个数a1,a2,...,an,要求从中选出一些数,可以把其中最多k个变成它自己的阶乘,然后选出的数求和,问最后和等于s的选法有多少种。

限制:
1 <= n <= 25; 0 <= k <= n; 1<= s <= 1e16; 1 <= ai <= 1e9

思路:
一般数据量20~30都会考虑中途相遇法,就是折半暴力。

ps:用三进制暴力会比直接深搜多一个常数10,因为三进制暴力要把数分解。

#include
#include
#include
#include 
using namespace std;
using namespace std::tr1;

#define LL unsigned __int64
#define MP make_pair
const int N=30;
const LL BEI=(LL)1e16+1;
int a[N];
unordered_map mp;
LL ans=0;

int n,k;
LL s;
LL f[50];
LL fac(int x){
	if(x<50) return f[x];
	return 0;
}
void predo(int x){
	LL sum=0;
	int p=0;
	int cnt=0;
	int cx=x;
	while(x){
		int ch=x%3;
		if(ch==1) sum+=(LL)a[p];
		else if(ch==2){
			if(fac(a[p])==0) return ;
			else sum+=fac(a[p]);
			++cnt;
			if(cnt>k) return ;
		}
		if(sum>s) return ;
		x/=3;
		++p;
	}
	//cout<<"q"<<' '<k) return ;
		}
		if(sum>s) return ;
		x/=3;
		++p;
	}
	//cout<s){
			f[i]=0;
			break;
		}
	}
	for(int i=0;i

深搜写法,比较短,比较快。

#include
#include
#include
#include
#include
using namespace std;
using namespace std::tr1;
#define PB push_back
#define LL __int64
LL S;
LL fac[50];
int a[30];
int n,k,lim;
LL ans=0;
unordered_map mp;
vector res1[30];
vector res2[30];
void gao(int cur,LL sum,int e){
	if(sum>S) return ;
	if(e>k) return ;
	if(cur==lim)
		res1[e].PB(sum);
	else{
		gao(cur+1,sum,e);
		gao(cur+1,sum+a[cur],e);
		if(a[cur]<19)
			gao(cur+1,sum+fac[a[cur]],e+1);
	}
}
int main(){
	fac[0]=1;
	for(int i=1;i<19;++i){
		fac[i]=fac[i-1]*i;
	}
	scanf("%d%d%I64d",&n,&k,&S);
	for(int i=0;i=0;--i){
		for(int j=0;j


你可能感兴趣的:(搜索)