zoukankan      html  css  js  c++  java
  • D Knapsack Cryptosystem 2019牛客暑假多校第九场 (折半枚举)

    链接:D.Knapsack Cryptosystem
    题意:给你一个长为n的序列,以及一个数s
    你要从序列中选择一些数字,使他们的和为m(满足组合唯一)
    并最后以01串的格式输出(0表示没有取,1表示取)
    思路:一开始题中给了一个 (背包加密算法的wiki) 然而跟这道题没有关系..
    此题数据范围值得注意:(1 <= n <= 36)          (0<= s< 9 e18)        (ai  < 2 e17)
    如果我们想要去暴搜,或者普通的状压dp,估计一个TLE,一个RE
    所以我们可以尝试折半状压去枚举,这里我们就开map去映射一下对应状态的和为多少


    #include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 40; map<ll,ll>G; ll arr[maxn],s; int n; int main(){ cin>>n>>s; { for(int i=0;i<n;i++){ cin>>arr[i]; } int mid = n/2; ll Max = 1<<(n/2); //2e18的状态 for(int i=0;i<Max;i++){ ll sum = 0; for(int j=0;j<mid;j++){ //从右往左数,取第j+1位上的值 if((i>>j)&1) sum += arr[j]; } G[sum] = i; } ll MMax = 1<<((n+1)/2); for(int i=0;i<MMax;i++){ ll sum = 0; for(int j=0;j<((n+1)/2);j++){ if(i>>j&1) sum += arr[mid+j]; } if(G.count(s-sum)){ ll k = G[s-sum]; int cnt = 0;//记录前导零个数 while(k){ //末位为1 cnt++; if(k&1) cout<<1; else cout<<0; k >>= 1; } while(cnt<mid) { cnt++; cout<<0; } cnt = 0; while(i){ cnt ++; if(i&1) cout<<1; else cout<<0; i >>= 1; } while(cnt<(n+1)/2) {cout<<0; cnt++;} return 0; } } } }
  • 相关阅读:
    兼容利器之X-UA-Compatible
    SQL Server之游标的基础知识
    SQL 按特定字段值排序
    NodeJS 开篇 牛刀小试
    临时表之IF-ELSE
    css中如何设置字体
    怎么做到不加班?
    C# .net中cookie值为中文时的乱码解决方法
    HTML5商城开发一 楼层滚动加载数据
    QQ浏览器X5内核问题汇总
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11372748.html
Copyright © 2011-2022 走看看