黄学长模拟day1 某种密码
关于某种密码有如下描述:某种密码的原文A是由N个数字组成,而密文B是一个长度为N的01数串,原文和密文的关联在于一个钥匙码KEY。若KEY=∑▒〖Ai*Bi〗,则密文就是原文的一组合法密码。
现在有原文和钥匙码,请编一个程序来帮助他统计到底有多少个符合条件的密文。
【输入数据】
第一行两个数N,KEY,意义同题目描述;
第二行N个数表示原文A,意义同题目描述。
【输出数据】
一个数ANS,表示对于原文A和KEY,有多少组可行的密文B。
【输入样例】
3 2
1 1 2
【输出样例】
2
【样例说明】
密文110,1*1+1*1+0*2=2
密文001,0*1+0*1+1*2=2
一共两组可行的密文。
【数据约定】
60%数据满足N<=25
100%数据满足N<=40,-maxlongint<=∑▒Ai<=maxlongint
/* 这道题作为第一题难度确实是不大,但一定要有这个优化的意识,如果纯粹搜索所有方案,时间无法承受,我们可以考虑到,当前面一些的值计算出来,后面的值等于说是在前面的基础上进行进一步的计算,我们于是考虑到去掉“在前面的基础上”这个指数级的冗余运算,通过后面和前面比较,先算前面的,后面的看有没有那个和他相加等于K的就行了,hash运算,注意sum可能是一个很大的负数 */ //我写的hash #include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<map> #include<vector> #define ll long long #define fo(i,l,r) for(int i = l;i <= r;i++) using namespace std; const ll sed = 31,Sed = 131,mod = 70177,Mod = 92311; struct dat{ ll v; ll a; }; int n; bool gt; vector<dat> h[mod]; ll a[105],key,ans,lm; inline void dfs(int pos,ll sum){ if(pos <= lm){ dfs(pos+1,sum+a[pos]); dfs(pos+1,sum); }else{ dat tmp; if(!gt) { ll ha = (sum + mod*100000) % mod; ll hb = (sum + Mod*100000) % Mod; for(int i = 0;i < h[ha].size();i++){ if(h[ha][i].v == hb){ h[ha][i].a++; return; } } tmp.v = hb; tmp.a = 1; h[ha].push_back(tmp); }else{ ll ha = (key - sum + mod*100000) % mod; ll hb = (key - sum + Mod*100000) % Mod; for(int i = 0;i < h[ha].size();i++){ if(h[ha][i].v == hb){ ans+=h[ha][i].a; break; } } } } } int main(){ freopen("password.in","r",stdin); freopen("password.out","w",stdout); cin>>n>>key; fo(i,1,n){ cin>>a[i]; } if(n == 1){ ans = (a[1] == key) + (0 == key); return 0; } lm = n >> 1; dfs(1,0); gt = true; lm = n; dfs((n >> 1)+1,0); cout<<ans; return 0; } //黄学长Map #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<map> #include<vector> #define ll long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } bool flag; ll ans; int n,cnt,key; int a[55]; map<int,int> b; void dfs(int x,int now) { if(x==cnt+1) { if(!flag)b[now]++; else ans+=b[key-now]; return; } dfs(x+1,now+a[x]); dfs(x+1,now); } int main() { //freopen("password.in","r",stdin); //freopen("password.out","w",stdout); n=read();key=read(); for(int i=1;i<=n;i++) a[i]=read(); cnt=n/2;dfs(1,0); flag=1;cnt=n;dfs(n/2+1,0); printf("%I64d",ans); return 0; }