说的是给了n个立方体,立方体从1标号到n,每个立方体上有一个数字, 你有 k 个机会 使得其中 k个数位他们自己的阶乘,(自然使用可以少于k次机会,每个立方体最多被使用1次) ,那么求出你从这n个立方体重选出任意个立方体使得 他们的和为S
n<25
可以知道直接使用n去枚举自然受不了, 我们将n个数字分为两部分来算,前面n/2个数字 我们枚举他们使用j次可以得到的数,然后后面的n-n/2个数再次使用这个方法,直接在dfs枚举的时候进行判断S-s 在前一个钟是否出现过,出现过就加起来。 分块处理
1 #include <iostream> 2 #include <algorithm> 3 #include <string.h> 4 #include <map> 5 #include<cstdio> 6 using namespace std; 7 typedef long long LL; 8 map<LL,int>mp[30]; 9 LL A[30]; 10 LL dp[30]; 11 LL time[1000000]; 12 int n,K; 13 LL S,ans; 14 void dfs(int p, int k, LL s){ 15 if(p==n/2){ 16 mp[k][s]++; 17 }else{ 18 dfs(p+1,k,s); 19 if(s+A[p]<=S)dfs(p+1,k,s+A[p]); 20 if(k+1<=K && A[p]<=18 && s+dp[A[p]] <=S ) dfs(p+1,k+1,s+dp[A[p]]); 21 } 22 } 23 void dfs1(int p, int k, LL s){ 24 if(p==n){ 25 for(int i =0; i+k<=K; i++) 26 if(mp[i].count(S-s)>0) ans+=mp[i][S-s]; 27 }else{ 28 dfs1(p+1,k,s); 29 if(s+A[p]<=S) dfs1(p+1,k,s+A[p]); 30 if(k+1<=K && A[p]<=18 && s+dp[A[p]]<=S) dfs1(p+1,k+1,s+dp[A[p]]); 31 } 32 } 33 int main() 34 { 35 36 37 dp[0]=1; 38 for(LL i=1; i<=18; i++) dp[i]=dp[i-1]*i; 39 ans=0; 40 scanf("%d%d%I64d",&n,&K,&S); 41 for(int i=0; i<n; i++) 42 scanf("%I64d",&A[i]); 43 dfs(0,0,0); 44 dfs1(n/2,0,0); 45 printf("%I64d\n",ans); 46 return 0; 47 }
codeforces E - Anya and Cubes 分块处理 暴力搜索
原文:http://www.cnblogs.com/Opaser/p/4381974.html