UOJ 310 黎明前的巧克力 FWT

2022-03-25 20:56:36 字數 1491 閱讀 7773

題目傳送門

題目大意:給你乙個序列,定義乙個子串行的權值表示子串行中元素的異或和,現在讓你選出兩個互不相交的子串行,求選出的這兩個子串行權值相等的方案數,$n,a_\leq 10^$

這是一道考察對$fwt$演算法理解的好題。然而我並不會

思路來自出題人的題解

假設權值最大值為$m$

暴力怎麼搞?揹包$dp$一下

定義$f(i,j)$表示現在遍歷到了第$i$個元素,選出的兩個子串行異或和為$j$的方案數,容易得到方程:

$f(i,j)=f(i-1,j)+2*f(i-1,j\;xor\;a_)$

時間複雜度$o(nm)$,可以獲得30分

看那個卷積形式,$fwt$?

時間複雜度$o(nmlogm)$,可以獲得..0分

我們發現每一層的生成函式裡只有兩個位置有值

假設現在我們遍歷到了第$i$個物品$a_$,第$i$層的生成函式長這個樣:

$f_(0)=1, f_(a_)=2$

其它位置都是0誒

對它進行fwt正變換,會發現正變換之後的陣列裡只有-1和3

因為$f_(0)$對每個位置都有+1的貢獻,而$f_(a_)$對每個位置有+2或-2點貢獻

重新考慮那個$0$分暴力。我們把每一層都正變換,然後對應位置相乘,再逆變換回來

我們可以想辦法快速求出對應位置相乘之後的陣列$f$,這樣再用一次逆變換就行了

我們只需要統計出每個位置上有幾個3相乘,設3的數量是$x$,-1的數量就是$n-x$,快速冪一下,就能得到$f$了

我們把貢獻積轉化成了指數上的貢獻和,發現只用一次正變換就行啦!

再用快速冪把貢獻和轉化成貢獻積。最後逆變換回來就行了

時間$o(mlogm)$

1 #include 2 #include 3 #include 4

#def_ne n1 (1<<20)+10

5#def_ne ll long long

6using

namespace

std;

7const

int p=998244353;8

9 template void read(_t &ret)

1013

while(c>='

0'&&c<='9')

14 ret=ret*fh;15}

1617

ll qpow(ll x,ll y)

1823

24void fwt_xor(int *s,int len,int

type)

2534}35

36int

n,ma,len,l;

37int

a[n1],s[n1];

3839

intma_n()

4053 fwt_xor(s,len,-1

);54 printf("

%d\n

",(s[0]-1+p)%p);

55return0;

56 }

uoj 310 UNR 2 黎明前的巧克力

題目描述 題解 考慮到選出的兩個集合的異或值為 0 所以我們可以看做找出集合,其異或值為 0 然後如果這個集合大小是 x 對答案的貢獻就是 2 x 所以我們考慮每個 i 對應乙個多項式 1 2x 只要我們把多項式乘起來即可 我們考慮 fwt 過程中 i 位置上的數對 j 位置的貢獻是數值乘上 1 不...

C UNR 2 黎明前的巧克力

evan 和 lyra 都是聰明可愛的孩子,兩年前,evan 開始為乙個被稱為uoj的神秘的oi組織工作,在 evan 與其他小夥伴的努力下,uoj不僅成了oi界原創比賽的典範,更是因ur這一 難度的存在而舉世聞名。然而今年,隨著 evan 前往世界彼岸,uoj一天天減少著他的活力,而就在oi歷新年...

UNR 2 黎明前的巧克力

解題思路 考慮乙個子集 s 的異或和如果為 0 那麼貢獻為 2 不難列出生產函式的式子,這裡的卷積是異或卷積。x 0 prod 2x 1 因為每一項只有兩項 x 0,x 有值,記 f i x 2x 1 f i x textf x 有 f i x sum 1 2 times 1 x s 不難發現 f ...