折半搜尋 某種密碼

2021-08-30 15:39:42 字數 1559 閱讀 7673

某種密碼

描述關於某種密碼有如下描述:某種密碼的原文a是由n個數字組成,而密文b是乙個長度為n的01數串,原文和密文的關聯在於乙個鑰匙碼key。

若key=∑(ai∗bi)key=∑(ai∗bi),則密文就是原文的一組合法密碼。

現在有原文和鑰匙碼,請編乙個程式來幫助他統計到底有多少個符合條件的密文。

輸入第一行兩個數n,key,意義同題目描述;

第二行n個數表示原文a,意義同題目描述。

輸出乙個數ans,表示對於原文a和key,有多少組可行的密文b。

樣例輸入

3 21 1 2

樣例輸出

2【樣例說明】

密文110,1∗1+1∗1+0∗2=21∗1+1∗1+0∗2=2

密文001,0∗1+0∗1+1∗2=20∗1+0∗1+1∗2=2

一共兩組可行的密文。

【資料約定】

60%資料滿足n<=25

100%資料滿足n<=40,-maxlongint<=∑ai<=maxlongint

analysis

雖然我沒有看出來,但這就是乙個0/1揹包的變種問題啊

key就是揹包容積,ai就是每個物品的容積,求恰好裝滿揹包的方案數。

是不是滿簡單的??

等等,再看看資料範圍,emmm……

這個包好像太大了一點

怎麼辦呢?既然ai不行就從n

nn下手

那麼小的資料範圍,暴力搜尋吧

但如果只是暴力搜尋的話,2

402^

240貌似行不通

怎麼辦怎麼辦?哈……2

402^

240不行,一半總可以搜出來吧

那我們就折半搞(以後這種資料範圍好像可以搜,又好像會掛,就可以試試折半了)

將物品集合均分成兩個交集為空,補集為全集的集合a、b,對集合a暴力列舉其所有子集中元素和並存入雜湊表(可重集),再對集合b暴力列舉每個子集的元素和s,同時查詢雜湊表中值為(key−s)的元素個數並計數。時間複雜度為o(2∗2n/2)=o(2n/2),可以接受。

code

#include

#include

#define ll long long

using

namespace std;

int n,a[50]

,b[50];

ll key;

tr1::unordered_mapint> m;

void

dfs(

int pos,

int end,ll sum)

dfs(pos+

1,end,sum+a[pos]);

dfs(pos+

1,end,sum);}

ll ans=0;

void

solve

(int pos,

int end,ll sum)

solve

(pos+

1,end,sum+a[pos]);

solve

(pos+

1,end,sum);}

intmain()

某種密碼 password

關於某種密碼有如下描述 某種密碼的原文a是由n個數字組成,而密文b是乙個長度為n的01數串,原文和密文的關聯在於乙個鑰匙碼key。若key ai bi 則密文就是原文的一組合法密碼。現在有原文和鑰匙碼,請編乙個程式來幫助他統計到底有多少個符合條件的密文。輸入資料 第一行兩個數n,key,意義同題目描...

2014 10 4模擬賽 某種密碼

某種密碼 password.關於某種密碼有如下描述 某種密碼的原文a是由n個數字組成,而密文b是乙個長度為n的01數串,原文和密文的關聯在於乙個鑰匙碼key。若key ai bi 則密文就是原文的一組合法密碼。現在有原文和鑰匙碼,請編乙個程式來幫助他統計到底有多少個符合條件的密文。輸入資料 第一行兩...

折半搜尋 meet in the middle

在使用搜尋的時候,當n過大2n會超時,這時候可以用折半搜尋,把時間複雜度降低到2n 2 1 具體方法 分別搜尋前一半,把狀態放入a陣列,搜尋後一半,把狀態放入b陣列,最後統計答案。一般meet in the middle的難點主要在於最後答案的組合統計。我們可以現將a或b陣列sort,讓其有序。然後...