zoukankan      html  css  js  c++  java
  • 2014.10.4模拟赛【某种密码】

    某种密码(password.*)

        关于某种密码有如下描述:某种密码的原文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


    题意是给定n个数,要求做01背包之后和为key的方案数

    首先n<=25的直接2^n爆搜就好了

    当n<=40的时候,有一种做法是类似“方程的解数”那题的前后分开暴力

    假设b[]是一个满足Σa[i]*b[i]=key的01序列

    首先,b[]数组必须刚好n个数

    显然b[]数组最多有2^40种不同的排列,直接爆搜会T

    但是我们把b[]的前n/2个元素暴力枚举出来,最坏情况下是2^20,用hash存起来

    然后再暴力枚举后n-n/2个,最坏也是2^20,统计答案的时候只要找前面跟它刚好匹配的方案数就好了

    比如找到一种和为a的方案,只要在哈希表中找前20个中和为key-a的方案数累加就好了

    这样复杂度降到(n/2)*2^(n/2)

    在考场上a[i]开了long long但是读入没有用%lld就只有70……蛋疼

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define LL long long
    #define mod 1000007
    #define deliver n/2
    using namespace std;
    struct hashing{
    	LL next,rep;
    	LL v;
    }hash[5000000];
    int head[mod];
    int n,m,cnt;
    LL ans;
    LL a[100];
    inline void ins(LL u,LL w)
    {
    	hash[++cnt].v=w;
    	hash[cnt].rep=1;
    	hash[cnt].next=head[u];
    	head[u]=cnt;
    }
    inline void insert(LL u,LL w)
    {
    	LL s=w%mod;while(s<0)s+=mod;
    	for(int i=head[s];i;i=hash[i].next)
    	  if (hash[i].v==w)
    	  {
    	  	hash[i].rep++;
    	  	return;
    	  }
    	ins(s,w);
    }
    inline int get(int u)
    {
    	LL w=(LL)(m-u);
    	LL s=w%mod;while (s<0)s+=mod;
    	for (int i=head[s];i;i=hash[i].next)
    	  if (hash[i].v==w)return i;
    	return -1;
    }
    int main()
    {
    	freopen("password.in","r",stdin);
    	freopen("password.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)scanf("%lld",&a[i]);
    	sort(a+1,a+n+1);
    	for(int i=0;i<=(1<<deliver)-1;i++)
    	  {
    	  	LL tot=0;
    	  	for (int j=1;j<=deliver;j++)
    	  	  if (i & (1<<(j-1)))tot+=a[j];
    	  	insert(tot,tot);
    	  }
    	for (int i=0;i<=(1<<(n-deliver))-1;i++)
    	{
    		LL tot=0;
    		for (int j=1;j<=n-deliver;j++)
    		  if (i & (1<<(j-1)))tot+=a[j+deliver];
    		int fnd=get(tot);
    		if (fnd!=-1)ans+=hash[fnd].rep;
    	}
    	printf("%lld
    ",ans);
    }
    

      

    ——by zhber,转载请注明来源
  • 相关阅读:
    Get distinct count of rows in the DataSet
    单引号双引号的html转义符
    PETS Public English Test System
    Code 39 basics (39条形码原理)
    Index was outside the bounds of the array ,LocalReport.Render
    Thread was being aborted Errors
    Reportviewer Error: ASP.NET session has expired
    ReportDataSource 值不在预期的范围内
    .NET/FCL 2.0在Serialization方面的增强
    Perl像C一样强大,像awk、sed等脚本描述语言一样方便。
  • 原文地址:https://www.cnblogs.com/zhber/p/4035891.html
Copyright © 2011-2022 走看看