zoukankan      html  css  js  c++  java
  • 黄学长模拟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;
    }
  • 相关阅读:
    插入排序java代码
    选择排序java代码
    break语句的作用
    while和do-while的区别
    if-else-if-else与switch的区别
    Java中基本类型的转换规则
    如何让计算机最高效的算出2乘以8?
    |和||的作用和区别
    &和&&的作用和区别
    i++和++i的作用和区别
  • 原文地址:https://www.cnblogs.com/hyfer/p/5990887.html
Copyright © 2011-2022 走看看