某種密碼
描述關於某種密碼有如下描述:某種密碼的原文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,讓其有序。然後...