2019牛客暑期多校训练营(第九场)D Knapsack Cryptosystem(折半枚举)

题目链接:https://ac.nowcoder.com/acm/contest/889/D

题目大意:从n个数中找出一些数,使得这些数的总和等于s,答案用”01“串表示

解题报告:将n个数分成两部分,然后折半枚举一下,前一部分共有$2^{\frac{n}{2}}$种个可能的情况,,每一种情况的和为w,在后一部分中找总和为$s-w$的情况,两个部分合并即为答案。

AC代码:

  1 #include<bits/stdc++.h>
  2 #define numm ch-48
  3 #define pd putchar(' ')
  4 #define pn putchar('\n')
  5 #define pb push_back
  6 #define fi first
  7 #define se second
  8 #define fre1 freopen("1.txt","r",stdin)
  9 #define fre2 freopen("2.txt","w",stdout)
 10 #define debug cout<<"debug"<<endl
 11 using namespace std;
 12 template <typename T>
 13 void read(T &res) {
 14     bool flag=false;char ch;
 15     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
 16     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
 17     flag&&(res=-res);
 18 }
 19 template <typename T>
 20 void write(T x) {
 21     if(x<0) putchar('-'),x=-x;
 22     if(x>9) write(x/10);
 23     putchar(x%10+'0');
 24 }
 25 typedef long long ll;
 26 const int maxn=40;
 27 const int maxm=505;
 28 const int mod=1e9+7;
 29 const int inv2=500000004;
 30 struct node {
 31     ll w,v;
 32     ll bit;
 33 }wtz[1<<(maxn>>1)];
 34 ll n,s;
 35 ll a[maxn];
 36  
 37 bool cmp(node &a,node &b) {
 38     return a.w<b.w;
 39 }
 40 int found(int l,int r,ll x) {
 41     int mid=0;
 42     while(l<r) {
 43         mid=(l+r)>>1;
 44         if(wtz[mid].w==x) return mid;
 45         else if(wtz[mid].w<x) l=mid+1;
 46         else if(wtz[mid].w>x) r=mid;
 47     }
 48     return mid;
 49 }
 50 void print(int x,int len) {
 51     char s[1<<(maxn>>1)];
 52     for(int i=0;i<len;i++) {
 53         s[i]=x%2;
 54         x/=2;
 55     }
 56     for(int i=len-1;i;i--)
 57         write(s[i]);
 58 }
 59 void solve() {
 60     ll n2=n/2;
 61     for(int i=0;i< 1<<n2;i++) {
 62         ll sw=0;
 63         for(int j=0;j<n2;j++)
 64             if(i>>j&1)
 65                 sw+=a[j];
 66         wtz[i].w=sw;
 67         wtz[i].bit=i;
 68     }
 69  
 70     sort(wtz,wtz+(1<<n2),cmp);
 71  
 72     for(int i=0;i< 1<<(n-n2);i++) {
 73         ll sw=0;
 74         for(int j=0;j< n-n2;j++)
 75             if(i>>j&1)
 76                 sw+=a[n2+j];
 77         if(sw<=s) {
 78 //            debug;
 79             ll pos=found(0,(1<<n2),s-sw);
 80 //            cout<<wtz[pos].w<<endl;
 81             if(wtz[pos].w+sw==s) {
 82                 int s[40];
 83                 for(int k=0;k<n;k++)
 84                     s[k]=0;
 85                 for(int k=0;k<n2;k++) {
 86                     if((wtz[pos].bit>>k&1))
 87                         s[k]=1;
 88                 }
 89                 for(int k=0;k<n-n2;k++) {
 90                     if(i>>k&1)
 91                         s[n2+k]=1;
 92                 }
 93                 for(int k=0;k<n;k++)
 94                     write(s[k]);
 95                 pn;
 96                 return ;
 97             }
 98         }
 99     }
100 }
101 int main()
102 {
103 //    #define local
104     #ifdef local
105         fre1;
106 //        fre2;
107     #endif // local
108     read(n),read(s);
109     for(int i=0;i<n;i++)
110         read(a[i]);
111     solve();
112     return 0;
113 }
代码在这里!

 

posted @ 2019-08-15 20:14  wuliking  阅读(225)  评论(0编辑  收藏  举报