• Knapsack Cryptosystem 牛客团队赛


    时限2s
    题意:

    第一行包含两个整数,分别是n(1 <= n <= 36)和s(0 <= s <9 * 10 18
    第二行包含n个整数,它们是{a i }(0 <a i <2 * 10 17)。
     {ai}就像在Merkle–Hellman背包密码系统中一样生成,因此存在一个解决方案,并且该解决方案是唯一的。
    如果数组{ai}是需要的输出1,不需要的输出0
    样例:
    输入

    8 1129
    295 592 301 14 28 353 120 236

    输出

    01100001

    思路:

    因为n是36,2^36明显会超时,所以用折半枚举;

    用两个map一个存前半段2^(n/2)的不同和以及输出状态

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define il inline
    #define it register int
    #define inf 0x3f3f3f3f
    #define lowbit(x) (x)&(-x)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define modd 998244353
    const int maxn=4e4+10;
    ll kk,a[43];
    int n;
    map<ll,int>m;
    map<ll,string>mp;
    int main(){
        scanf("%d%lld",&n,&kk);
        for (it i = 0; i < n; i++){
            scanf("%lld", &a[i]);
        }
        for (it i = 0; i < 1 << (n / 2); i++){
            ll sum = 0;
            string c = "";
            for (it j = 0; j < n / 2; j++){
                if ((i >> j) & 1){
                    sum += a[j];
                    c+= "1";
                }
                else{
                    c += "0";
                }
            }
            m[sum]++;
            mp[sum] = c;
        }
        int wk=n - n / 2;
        for (it i = 0; i < 1 << wk; i++){
            ll sum = 0;
            string c = "";
            for (it j = 0; j < wk; j++){
                if ((i >> j) & 1) {
                    sum += a[j + n / 2];
                    c += "1";
                }
                else{
                    c += "0";
                }
            }
            if(m[kk - sum]==1){
                cout << mp[kk - sum] << c << endl;
            }
        }
        return 0;
    }
  • 相关阅读:
    看到差距了,受打击
    数码相机选购指南(应小麻之作)
    sorry
    ACM集训第一天
    没事了,放心了,回到自己,又有些失落
    黑暗世界的一线光明

    无忧无虑的睡去,是一种奢华的享受(新)
    一些废话
    对事不对人
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/12347551.html
Copyright © 2020-2023  润新知