CF 297 div2 E. Anya and Cubes (hash+dfs)

来源:互联网 发布:毕向东java笔记百度云 编辑:程序博客网 时间:2024/05/24 05:49

题目:http://codeforces.com/contest/525/problem/E

题意:输入N,K,S。N代表接下来要输入的数字序列{a1,a2...an}的个数,K代表有K次机会marks使其中一个数ai变成ai的阶乘,求选x个数(1<=x<=N)使用y次marks(0<=y<=K)使它们的和为S的方案数。

分析:枚举一半的数字,将结果存进hash表,然后枚举后面一半的数字在hash表里面查询。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <set>#include <map>#include <vector>#include <string>using namespace std;typedef long long LL;#define MOD 1000019#define MAXN 3000000LL a[10000];LL fac[]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800,87178291200,1307674368000,20922789888000,355687428096000,6402373705728000};struct node{LL value;LL use;LL count;int next;};struct Hash{LL Table[MOD],cnt;node List[MAXN];void Clear(){cnt=0ll;for(int i=0;i<MOD;i++)Table[i]=-1ll;}void Insert(LL v,LL use){LL hash=v%MOD;LL temp=Table[hash];while(temp!=-1){if(List[temp].value==v && List[temp].use==use){List[temp].count++;return ;}temp=List[temp].next;}List[cnt].value=v;List[cnt].use=use;List[cnt].count=1;List[cnt].next=Table[hash];Table[hash]=cnt;cnt++;}LL Search(LL v,LL use){LL hash=v%MOD;hash=Table[hash];LL ret=0; while(hash!=-1){if(List[hash].value==v && List[hash].use<=use)ret+=List[hash].count;hash=List[hash].next;}return ret;}}H;LL S,K,N,ans;void dfs1(LL cur_n,LL n,LL v,LL u){if(cur_n>n+1 || u>K || v>S)return ;if(cur_n==n+1){H.Insert(v,u);return ;}if(a[cur_n]<19)dfs1(cur_n+1,n,v+fac[a[cur_n]],u+1);dfs1(cur_n+1,n,v+a[cur_n],u);dfs1(cur_n+1,n,v,u);}void dfs2(LL cur_n,LL n,LL v,LL u){if(cur_n>n+1 || u>K || v>S)return ;if(cur_n==n+1){ans+=H.Search(S-v,K-u);return ;}if(a[cur_n]<19)dfs2(cur_n+1,n,v+fac[a[cur_n]],u+1);dfs2(cur_n+1,n,v+a[cur_n],u);dfs2(cur_n+1,n,v,u);}int main(){LL i,j;cin>>N>>K>>S;for(i=0;i<N;i++)cin>>a[i];ans=0;H.Clear();dfs1(0ll,N/2-1ll,0ll,0ll);dfs2(N/2ll,N-1ll,0ll,0ll);cout<<ans<<"\n";    return 0;}



0 0