JZOJ4841 平衡的子集

2021-07-25 06:59:44 字數 1148 閱讀 3800

有n個人,每個人的力氣為m(i)。從這n個人中選出若干人,如果這些人可以分成兩組且兩組力氣之和完全相等,則稱為乙個合法的選法,問有多少種合法的選法?

請注意這裡是選人的方案而不是分組的方案。

我們考慮暴力,時間複雜度o(

320) ,顯然不能接受。

我們假設分進某一組權wi

為-1或1,不選為0,那麼每個人和的貢獻就是wi

mi。於是我們可以先搜尋前面一半的元素,然後我們知道跨越兩邊的選法左邊和右邊的貢獻和為0,憑藉此我們就可以在搜尋後面一半元素的時候順便統計選法跨越中間的方案數,然後判重即可。

對於判重的理解:由於我們統計的是選人的方案,所以可能某一種選法的不同兩種分組方法的貢獻相等,然而其中乙個是沒有用的。

那麼有了這個有什麼用呢?這首先保證你答案不會多,其次在加進狀態時若發現貢獻一樣,選法相同的分配的狀態可以不用記錄。

#include

#include

#include

#define fo(i,j,k) for(int i=j;i<=k;i++)

#define fd(i,j,k) for(int i=j;i>=k;i--)

#define rep(i,x) for(int i=ls[x];i;i=nx[i])

#define max 22

#define m 1048577

#define s 1025

#define nn 44

using namespace std;

int z,n,n;

int a[max],h[m],er[max];

int ans=0;

bool bz[s][s];

int nx[m],ls[m],to[m],num=0;

int hash(int x)

void link(int x,int y)

void dfs(int x,int s,int st)

}if(tf) link(t,st);

return;

}fo(i,-1,1)

}void

get(int x,int s,int st)

}return;

}fo(i,-1,1)

}int main()

Jzoj4841 平衡的子集

夏令營有n個人,每個人的力氣為m i 請大家從這n個人中選出若干人,如果這些人可以分成兩組且兩組力氣之和完全相等,則稱為乙個合法的選法,問有多少種合法的選法?這道題我們拷打資料範圍後知道應該是折半搜尋了 但是似乎不是那麼好做 我們考慮如何搜尋,顯然每個人有三種狀態,在隊伍1中,在隊伍2中和沒有被選入...

洛谷4841 城市規劃

題意 求 n 個點的簡單 無重邊無自環 有標號無向連通圖數目。思路 設 f n 為點數為 n 的無向連通圖的數量,g n 為點數為 n 的無向圖的數量,可以知道 g n 2 可以這麼理解,n 個點中取兩個點連邊,一共有 c n 2 種,每個邊存在連或不連兩種可能。同時有 g n sum nc f i...

HDU 4841 圓桌問題

acm模版 這個題簡單的來就是暴力列舉約瑟夫環,當然,太暴力也不好,適當的用資料結構優化一下也是有必要的,這裡用向量維護,成功水過。include include include include include using namespace std const int maxn 4e4 const...