「NOIP模拟赛」某种密码
关于某种密码有如下描述:某种密码的原文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
题解
由于sum{a[i]}太大所以不考虑背包
可以把n个数分成两半搜索。。。
然后用个哈希表或者map
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#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; } |
Subscribe