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.
示例1
輸入
復制
8 1129
295 592 301 14 28 353 120 236
輸出
復制
01100001
說明
This is the example in Wikipedia.
示例2
輸入
復制
36 68719476735
1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912 1073741824 2147483648 4294967296 8589934592 17179869184 34359738368
輸出
復制
111111111111111111111111111111111111

題目大意:
先輸入一個數字nnn,代表有一個大小為nnn的數組(1≤n≤36)(1\le n \le 36)(1n36),再輸入一個數字sss,下面一行輸入nnn個數字,要從這nnn個數字里面選取任意個數字使其和等于sss,通過輸出一串長度為nnn的01字符串來表示選或不選。

解題思路:
首先想到的是枚舉所有選擇的情況,但發現其時間復雜度已經到達了2362^{36}236,明顯會超時,因此想到折半的方法,將其時間復雜度降為2182^{18}218,接近1e61e61e6,也就是將數組分為兩部分,枚舉前半部份所有的選擇情況,將其和存在一個數組中,同理處理后半部分,后面判斷其和是否能組成sss,僅需枚舉前半部分的所有情況,通過用 s?s-s?前半部分的和 ,查找其在后半部分是否存在即可。

代碼:

//#pragma GCC optimize(3,"Ofast","inline")
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <set>
#include <utility>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define inf 0x3f3f3f3f
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define lep(i,l,r) for(int i=l;i>=r;i--)
#define ms(arr) memset(arr,0,sizeof(arr))
//priority_queue<int,vector<int> ,greater<int> >q;
const int maxn = (int)1e5 + 5;
const ll mod = 1e9+7;
ll arr[40];
struct node1
{ll num;int id;
}sum_qian[1001000];
struct node2
{ll num;int id;
}sum_hou[1001000];
bool cmp1(node1 a,node1 b) {return a.num<b.num;
}
bool cmp2(node2 a,node2 b) {return a.num<b.num;
}
ll get_sum(int id,int len) {ll sum=0;while(id) {if(id&1) {sum+=arr[len];}id>>=1;len++;}return sum;
}
int main() 
{#ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin);#endif//freopen("out.txt", "w", stdout);//ios::sync_with_stdio(0),cin.tie(0);int n;ll s;cin>>n>>s;rep(i,1,n) {cin>>arr[i];}int nape=n/2;for(int i=0;i<(1<<nape);i++) {sum_qian[i].num=get_sum(i,1);sum_qian[i].id=i;}int len_qian=(1<<nape);int t1=nape;int start=nape+1;nape=n-nape;for(int i=0;i<(1<<nape);i++) {sum_hou[i].num=get_sum(i,start);sum_hou[i].id=i;}int len_hou=(1<<nape);int t2=nape;sort(sum_qian,sum_qian+len_qian,cmp1);sort(sum_hou,sum_hou+len_hou,cmp2);int qian=-1,hou=-1;for(int i=0;i<len_qian;i++) {ll nape;if(s>=sum_qian[i].num)nape=s-sum_qian[i].num;else continue;int l=0,r=len_hou;int id=-1;while(r-l>1) {int mid=(r+l)>>1;if(sum_hou[mid].num==nape) {id=sum_hou[mid].id;break;}else if(sum_hou[mid].num>nape) {r=mid;}else {l=mid;}}if(id!=-1) {qian=sum_qian[i].id;hou=id;break;}}if(qian!=-1&&hou!=-1) {for(int i=1;i<=t1;i++) {cout<<(qian&1);qian>>=1;}for(int i=1;i<=t2;i++) {cout<<(hou&1);hou>>=1;}cout<<endl;}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/536258.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/536258.shtml
英文地址,請注明出處:http://en.pswp.cn/news/536258.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

All men are brothers【并查集+數學】

鏈接&#xff1a;https://ac.nowcoder.com/acm/contest/889/E 來源&#xff1a;牛客網 題目描述 Amy asks Mr. B problem E. Please help Mr. B to solve the following problem. There are n people, who don’t know each other at the beginning. There are m turns. In e…

Light bulbs【差分】

19.98% 1000ms 8192K There are NN light bulbs indexed from 00 to N-1N?1. Initially, all of them are off. A FLIP operation switches the state of a contiguous subset of bulbs. FLIP(L, R)FLIP(L,R)means to flip all bulbs xx such that L \leq x \leq RL≤x≤R. S…

Digit sum【暴力+打表】

Digit sum 33.57% 2000ms 131072K A digit sum S_b(n)S b ? (n) is a sum of the base-bb digits of nn. Such as S_{10}(233) 2 3 3 8S 10 ? (233)2338, S_{2}(8)1 0 0 1S 2 ? (8)1001, S_{2}(7)1 1 1 3S 2 ? (7)1113. Given NN and bb, you need to calcu…

P1040 加分二叉樹【dp+深搜】

題目描述 設一個nn個節點的二叉樹tree的中序遍歷為&#xff08;1,2,3,…,n1,2,3,…,n&#xff09;&#xff0c;其中數字1,2,3,…,n1,2,3,…,n為節點編號。每個節點都有一個分數&#xff08;均為正整數&#xff09;&#xff0c;記第ii個節點的分數為di,treedi,tree及它的每個子樹…

Helloworld【C#】

c#Helloworld 題目描述 請輸出樣例所示內容 輸出 樣例輸出 ********** Hello,world! ********** using System;namespace ConsoleApp1 {class Program{static void Main(string[] args){Console.WriteLine("**********");Console.WriteLine("Hello,world!&…

判斷閏年【C#】

判斷閏年 題目描述 使用C#編寫一個控制臺應用。輸入-一個年份&#xff0c;判斷是否潤年(被4整除&#xff0c;且不被100整除&#xff0c;或者被400整除)。 是閏年輸出yes&#xff0c;不是輸出no 輸入 一個年份 輸出 yes或者no 樣例輸入 1996 樣例輸出 yes using Syst…

采用遞歸求第n位數【C#】

題目描述 一數列的規則如下&#xff1a;1、1、2、3、5、8、13、21、34......。求第n位數是多少&#xff1f; 輸入 輸入一個正整數&#xff0c;代表求第幾位數字 輸出 輸出第n位數字 樣例輸入 30 樣例輸出 832040 提示 輸入數字必須大于零 using System;namespace C…

歌手的分數【C#】

歌手的分數 題目描述 一青年歌手參加比賽。使用C#編寫-一個控制臺應用&#xff0c;輸入10位評委打分(分值只能為正整數)&#xff0c;計算并輸出歌手的平均分(去掉一一個最高分和一一個最低分)。平均分以double數據類型輸出。 輸入 1 2 3 4 5 6 7 8 9 10 輸出 5.5 樣例輸…

冒泡排序算法(C#)

冒泡排序算法&#xff08;C#&#xff09; 題目描述 使用C#編寫一個控制臺應用。輸入10個整數存入數組中&#xff0c;然后使用冒泡排序算法對一維數組的元素從小到大進行排序&#xff0c;并輸出。 輸入 在控制臺中輸入數字&#xff0c;存入一維數組 輸出 輸出排序后的數…

水仙花數【C#】

題目描述 春天是鮮花的季節&#xff0c;水仙花就是其中最迷人的代表&#xff0c;數學上有個水仙花數&#xff0c;他是這樣定義的&#xff1a; “水仙花數”是指一個三位數&#xff0c;它的各位數字的立方和等于其本身&#xff0c;比如&#xff1a;1531^35^33^3。 現在要求輸出…

C#異或運算符的使用【C#】

C#異或運算符的使用 題目描述 編寫一個控制臺應用&#xff0c;采用異或運算符&#xff0c;實現兩個整型變量值的交換。并在Program類的Main進行驗證。 輸入 依次輸入2個整數 輸出 輸出交換前、后兩個變量的值 樣例輸入 12 78樣例輸出 before exchange first12,second7…

C#類方法【C#】

C#類方法 題目描述 在類Class1中&#xff0c;編寫一個類方法IsEven(string number)用于輸出參數的奇偶性。并在Program類的Main進行驗證性輸出。 class Program { static void Main(string[] args) { Console.Write("Input Integer:&quo…

C#中的Switch語句【C#】

C#中的Switch語句 題目描述 編寫一個控制臺應用&#xff0c;實現以下功能&#xff1a;根據輸入的字符&#xff0c;輸出通過、不通過和輸入成績無效。 &#xff08;1&#xff09;無論輸入A、B、C、D&#xff0c;都輸出通過&#xff1b; &#xff08;2&#xff09;輸入E&#x…

c#輸出最大值、最小值和平均值(A)【C#】

c#輸出最大值、最小值和平均值(A) 題目描述 使用C#編寫一個控制臺應用。輸入10個正整數存入數組中&#xff0c;輸出最大值、最小值和平均值 輸入 輸入10個正整數 輸出 最大值、最小值和平均值 樣例輸入 1 2 3 4 5 6 7 8 9 10 樣例輸出 10 1 5.5 using System;namesp…

c#輸出最大值、最小值和平均值(B)【C#】

c#輸出最大值、最小值和平均值&#xff08;B&#xff09; 題目描述 使用C#編寫一個控制臺應用。輸入若干個正整數存入數組中&#xff08;輸入exit表示輸入結束&#xff09;&#xff0c;輸出最大值、最小值和平均值輸入 輸入若干個正整數存入數組中輸出 輸出最大值、最小值和平…

C#提取文件名【C#】

C#提取文件名 題目描述 假設有一個字符串包含了文件名、擴展名和路徑&#xff0c;如strFileName“D:\C#程序設計\實驗3\MyFile.TXT”。請使用C#編寫一個靜態方法&#xff0c;該方法能夠取出路徑中的文件名“MyFile.TXT”。 輸入 一個包含了文件名&#xff0c;擴展名和路徑的…

C#解密出生日期【C#】

C#解密出生日期 題目描述 使用C#編寫一個靜態方法。該方法能夠根據出生日期&#xff0c;&#xff08;1&#xff09;計算此人的年齡&#xff1b;&#xff08;2&#xff09;計算從現在到其60周歲期間&#xff0c;總共多少天。 輸入 一個人的出生日期&#xff1b; 輸出 第一…

C#判斷回文字符串【C#】

C#判斷回文字符串 題目描述 使用C#編寫一個靜態方法。該方法能夠判斷字符串是否是“回文”&#xff08;即順讀和逆讀相同的字符串&#xff09;。 輸入 一個字符串&#xff1b; 輸出 如果是回文字符串&#xff0c;則輸出“yes”&#xff0c;否則輸出“no”&#xff1b; 樣…

猜數【C#】

猜數 題目描述 編寫一個控制臺程序。以控制臺方式輸入整數&#xff0c;且調用Class1類CompareNum方法判斷是否猜中&#xff0c;給出大了、小了、猜中三種提示。輸入exit表示輸入結束。 輸入 無 輸出 太小了 太大了 猜中了 提示 若輸入的既不是數字&#xff0c;又不是ex…

簡單類及成員實例【C#】

簡單類及成員實例&#xff08;C#&#xff09; 題目描述 簡單類及成員實例。定義了如下圖所示類Student&#xff0c;根據下圖和給出代碼&#xff0c;補寫缺失的代碼。 using System; namespace sample{ class Student { public string studentid;//學號 p…