給出
n n
個數a1
,a2,
...,
an' role="presentation" style="position: relative;">a1,
a2,.
..,a
na1,
a2,.
..,a
n,問最多選出多少個數使得這些數的異或和為0。 n,
ai≤5
∗105 n,a
i≤5∗
105
震驚!老年退役選手居然開始寫題解了。
這次回家本來也沒打算寫題的,但是在今早某人問了我這個題,想了快乙個小時終於會了,然後就用睡覺的時間把這題過掉了。剛好現在閒得無聊就過來把題解寫一下也順便證明下自己還活著。
咳咳咳,那現在就要開始口胡了。
我們可以轉化成選出最少的數使得他們的異或和等於整個序列的異或和,設為w,不難發現答案不超過lo
g(ai
) log
(ai)
,不然的話選出的數一定是乙個線性相關組。
一開始的想法是列舉答案,那麼問題就轉化成了對某個
k k
,求所有大小為
k' role="presentation" style="position: relative;">k
k的子集能否異或出w。這個顯然可以用fwt來做,複雜度是倆log,有點虛。
接著想到或許可以二分,但這個顯然是不滿足二分性的,怎麼辦呢?那麼我們可以變成求大小至多為k的子集能否異或出w,怎麼實現呢?只要讓初始生成函式的零次項係數為1即可。
這樣複雜度就變為了o(
nlog
(n)l
og(l
og(n
))) o(n
log(
n)lo
g(lo
g(n)
))
,跑的飛快。
#include
#include
#include
#include
#include
const int n=1048591;
const int mod=10007;
const int ny2=(mod+1)/2;
int n,a[n],po[23][n],bin[23];
void fwt(int
*a,int l,int r)
}void dwt(int
*a,int l,int r)
}int main()
a[0]=1;
if (!w)
fwt(a,0,bin[20]-1);
for (int i=0;i20];i++) po[0][i]=1;
for (int j=1;j<=20;j++)
for (int i=0;i20];i++) po[j][i]=po[j-1][i]*a[i]%mod;
int l=1,r=20;
while (l<=r)
if (r==20) puts("0");
else
printf("%d\n",n-(r+1));
return
0;}
牛客 多校賽一
a lgv演算法 抄一波 牛客的解釋 wiki 沒耐心看了 lgv 演算法 lindstr m gessel viennot lemma 求以上矩陣的行列式,其中 e a,b 是從a到b的方法數,帶入求行列式即可得到 a1,a2,an 到 b1,b2,bn 的所有不相交路徑的種數 再看這道題,其實就...
2018牛客多校3
h diff prime pairs 1 3 1 5 1 7 1 11.2 3 2 5 2 7 2 11.3 3 3 5 3 7 3 11.4 3 4 5 4 7 4 11.打個素數表 用素數篩一遍 includeusing namespace std bool a 11111111 int zs ...
牛客多校 Ternary String (數論)
示例1輸入複製3 000012 22輸出複製3 9345 思路 1.如果遇到了 0,t 2.如果遇到了1,t t 2 2 因為之前經歷了t,那麼就會派生出來t個0,加上乙個1的時間 2 就是上式了 3.如果遇到了2,t 3 2 t 1 可以類似於2來想,經過了t後到了乙個2 會變成這樣 211010...