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 }
所谓人生,一半惊喜,一半遗憾