2019牛客暑期多校训练营(第九场)D.Knapsack Cryptosystem

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019牛客暑期多校训练营(第九场)D.Knapsack Cryptosystem相关的知识,希望对你有一定的参考价值。


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

题目描述
Amy asks Mr. B  problem D. Please help Mr. B to solve the following problem.

 

Amy wants to crack Merkle–Hellman knapsack cryptosystem. Please help it.

 

Given an array ai with length n, and the sum s.

Please find a subset of ai, such that the sum of the subset is s.

 

For more details about Merkle–Hellman knapsack cryptosystem Please read

​https://en.wikipedia.org/wiki/Merkle%E2%80%93Hellman_knapsack_cryptosystem​

​https://blog.nowcoder.net/n/66ec16042de7421ea87619a72683f807​

Because of some reason, you might not be able to open Wikipedia.

Whether you read it or not, this problem is solvable.

输入描述:

 
The first line contains two integers, which are n(1 <= n <= 36) and s(0 <= s < 9 * 1018)

The second line contains n integers, which are ai(0 < ai < 2 * 1017).

 

ai is generated like in the Merkle–Hellman knapsack cryptosystem, so there exists a solution and the solution is unique.

Also, according to the algorithm,  for any subset sum s, if there exists a solution, then the solution is unique.

输出描述:
Output a 01 sequence.If the i-th digit is 1, then ai is in the subset.
If the i-th digit is 0, then ai is not in the subset.

题意:

n个数,一个K,问你这n个数中哪几个数的加和是n,并用1标注出来?

思路:

折半搜索

 

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int n;
LL k,ans;
LL a[100];
int vis[100];
map<LL,LL>mp;
void dfs1(int pos,int en,LL sta,LL sum)


if(pos==en+1)


if(sum==k)

ans=sta;
return;

if(mp[sum]==0)

mp[sum]=sta;
// cout<<sum<<" "<<sta<<endl;

return;


if(sum==k)

ans=sta;
return;

if(mp[sum]==0)

mp[sum]=sta;
// cout<<sum<<" "<<sta<<endl;

//cout<<sum<<" "<<sta<<endl;

dfs1(pos+1,en,sta,sum);
dfs1(pos+1,en,sta|(1LL<<pos),sum+a[pos]);


void dfs2(int pos,int en,LL sta,LL sum)


if(pos==en+1)

if(sum==k)


ans=sta;
return ;

if(mp[k-sum]!=0)

ans=mp[k-sum]+sta;

return ;


if(sum==k)

ans=sta;
return ;


if(mp[k-sum]!=0)

ans=mp[k-sum]+sta;



dfs2(pos+1,en,sta,sum);
dfs2(pos+1,en,sta|(1LL<<pos),sum+a[pos]);



int main()

scanf("%d%lld",&n,&k);
for(int i=1; i<=n; i++)

scanf("%lld",&a[i]);

ans=0;
int mid=(n+1)/2;

if(ans==0)
dfs1(1,mid,0,0);

if(ans==0)
dfs2(mid+1,n,0,0);


for(int i=1; i<=n; i++)

if((ans>>i)&1)

printf("1");

else
printf("0");





return 0;
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
using namespace std;
const int N=40;
map<ll ,ll >mp;
ll index[N],a[N],target;
int n,mid;
ll ans;
void init()

index[1]=1;
for(int i=2;i<=N;i++)
index[i]=index[i-1]*2;

void DFS(int pos,ll sta,ll sum,int en)

if(pos==en+1)

if(pos==mid)

if(sum==target)
ans=sta;
mp[sum]=sta;;

else

if(mp[target-sum]!=0)
ans=sta+mp[target-sum];

return ;

DFS(pos+1,sta,sum,en);
DFS(pos+1,sta+index[pos],sum+a[pos],en);

int main()

init();
scanf("%d%lld",&n,&target);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
mid=n/2+1;
ans=0;

if(target) DFS(1,0,0,n/2);
if(!ans) DFS(n/2+1,0,0,n);

for(int i=1;i<=n;i++)

if(ans&1)
cout<<"1";
else
cout<<"0";
ans>>=1;

cout<<endl;
return 0;

 

以上是关于2019牛客暑期多校训练营(第九场)D.Knapsack Cryptosystem的主要内容,如果未能解决你的问题,请参考以下文章

2019杭电多校第九场

2019 杭电多校 第九场

Rikka with Game[技巧]----2019 杭电多校第九场:1005

2021牛客暑期多校训练营2

2021牛客暑期多校训练营4

2021牛客暑期多校训练营9