题目连接:
http://codeforces.com/contest/525/problem/E
题意:
n个数,k个魔法棒,s为所求的数,然后让你找有多少种方法,能够使的这n个数之和为s,其中一个魔法棒可以使的一个数变成他的阶乘。
题解:
第一种:http://blog.csdn.net/weizhuwyzc000/article/details/50043151
对于每一层,有3种决策: 不选这个数, 选择这个数, 选择这个数的阶乘。 递归深度最大25, 时间复杂度O(3^25), 太大了, 要想办法降低时间复杂度。 还记得之前的简化版吗? 我们在四个集合中每个集合选择一个数字相加,问是否等于一个数S, 我们的方法是预处理三个集合中所有的情况,然后二分。 该题也可以采取相同的策略: 进行两次dfs, 每次递归深度n/2,这样就成功将复杂度降低到O((3^13)*log(3^13)) 。 这是理论上界, 事实上这里面有很多重复的,时间复杂度并没有那么高。
第二种:http://www.cnblogs.com/qscqesze/p/4371851.html
折半搜索
对于每一个数,都有三种策略,拿,不拿,使用魔法棒
那么我们就直接折半搜索然后扔进一个map里面,然后就查询就好啦
13^3*12^3=3 796 416;
复杂度算的刚刚好呀= = (没看懂怎么算的
学到了 折半搜索降低复杂度 这个折半的意思是预先算出一半的结果,再从后一半找到sum-ans1。
还有就是map的运用 按first从小到大默认排序,如果first是结构体, 可以在结构体中写优先级的函数,map就会自动排序啦
代码一:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define mem(a) memset(a,0,sizeof(a)) 5 #define mp(x,y) make_pair(x,y) 6 const int INF = 0x3f3f3f3f; 7 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 8 inline ll read(){ 9 ll x=0,f=1;char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 11 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 12 return x*f; 13 } 14 ////////////////////////////////////////////////////////////////////////// 15 const int maxn = 1e5+10; 16 ll n,k,s; 17 ll a[30],ans; 18 ll p[30]; 19 20 struct node{ 21 ll sum, y; 22 node(ll ss=0, ll kk=0):sum(ss), y(kk) {} 23 bool operator < (const node& rhs) const { 24 if(sum==rhs.sum) return y<rhs.y; 25 return sum < rhs.sum; 26 } 27 }; 28 29 map<node,int> mp; 30 map<node,int>::iterator it; 31 32 void dfs1(int nn,int kk,ll ss){ 33 if(k < kk) return ; 34 if(ss > s) return ; 35 if(nn > n/2){ 36 node t(ss,kk); 37 mp[t]++; 38 return ; 39 } 40 41 dfs1(nn+1,kk,ss); 42 dfs1(nn+1,kk,ss+a[nn]); 43 if(a[nn] <= 20) dfs1(nn+1,kk+1,ss+p[a[nn]]); 44 } 45 46 void dfs2(int nn,int kk,ll ss){ 47 if(k < kk) return ; 48 if(ss > s) return ; 49 if(nn > n){ 50 it = mp.lower_bound(node(s-ss,0)); 51 for( ; it!=mp.end(); it++){ 52 if(it->first.sum==s-ss && k-it->first.y >= kk) ans += it->second; 53 if(it->first.sum != s-ss) break; 54 } 55 return ; 56 } 57 58 dfs2(nn+1,kk,ss); 59 dfs2(nn+1,kk,ss+a[nn]); 60 if(a[nn] <= 20) dfs2(nn+1,kk+1,ss+p[a[nn]]); 61 } 62 63 int main(){ 64 p[1] = 1; 65 for(int i=2; i<=20; i++) 66 p[i] = i*p[i-1]; 67 68 n = read(), k = read(), s = read(); 69 for(int i=1; i<=n; i++) 70 a[i] = read(); 71 72 int mid = n/2; 73 dfs1(1,0,0); 74 dfs2(mid+1,0,0); 75 76 cout << ans << endl; 77 78 return 0; 79 }
代码二:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define mem(a) memset(a,0,sizeof(a)) 5 #define mp(x,y) make_pair(x,y) 6 const int INF = 0x3f3f3f3f; 7 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 8 inline ll read(){ 9 ll x=0,f=1;char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 11 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 12 return x*f; 13 } 14 ////////////////////////////////////////////////////////////////////////// 15 const int maxn = 1e6+10; 16 17 struct node{ 18 ll sum,key; 19 }bef[maxn]; 20 ll p[30],cubes[30]; 21 ll n,k,s,cnt,ans; 22 map<ll,ll> mp[30]; 23 map<ll,ll>::iterator it; 24 25 void dfs1(ll nn,ll kk,ll ss){ 26 if(ss > s) return ; 27 if(kk > k) return ; 28 if(nn > n/2){ 29 bef[++cnt].sum = ss; 30 bef[cnt].key = kk; 31 return ; 32 } 33 dfs1(nn+1,kk,ss); 34 dfs1(nn+1,kk,ss+cubes[nn]); 35 if(cubes[nn] <= 20) dfs1(nn+1,kk+1,ss+p[cubes[nn]]); 36 } 37 38 void dfs2(ll nn,ll kk,ll ss){ 39 if(ss > s) return ; 40 if(kk > k) return ; 41 if(nn > n){ 42 mp[kk][ss]++; 43 return ; 44 } 45 dfs2(nn+1,kk,ss); 46 dfs2(nn+1,kk,ss+cubes[nn]); 47 if(cubes[nn] <= 20) dfs2(nn+1,kk+1,ss+p[cubes[nn]]); 48 } 49 50 int main(){ 51 n = read(), k = read(), s = read(); 52 for(int i=1; i<=n; i++) 53 cubes[i] = read(); 54 p[1] = 1; 55 for(int i=2; i<=20; i++) 56 p[i] = i*p[i-1]; 57 58 dfs1(1,0,0); 59 dfs2(n/2+1,0,0); 60 61 ans = 0; 62 for(int i=1; i<=cnt; i++) 63 for(int j=0; j<=k-bef[i].key; j++) 64 ans += mp[j][s-bef[i].sum]; 65 66 cout << ans << endl; 67 68 return 0; 69 }