洛谷6097 模板 子集卷積

2022-05-14 13:54:06 字數 1407 閱讀 7222

點此看題面

大致題意:給定\(a_,b_\),求\(c_\)滿足\(c_k=\sum_a_ib_j\)。

做這個之前,要先了解\(fwt\)。

考慮只要用\(fwt\)做或卷積,就可以輕鬆滿足\(i|j=k\)這一限制,可要同時滿足\(i\&j=0\),似乎沒法直接搞。

但是,稍加分析我們就會發現,這兩個限制放在一起其實會產生乙個奇妙的性質。

因為\(i\&j=0\),所以\(i\)和\(j\)不可能在同一位上存在\(1\),而\(i|j=k\),則\(k\)的每一位上的\(1\)應該被恰好分給\(i\)和\(j\)的其中乙個。

換言之,\(i\)和\(j\)二進位制下\(1\)的個數之和等於\(k\)二進位制下\(1\)的個數。

於是,我們定義\(f_,g_\)表示:(\(cnt(j)\)為\(j\)二進位制下\(1\)的個數)

\[f_=\begina_j&i=cnt(j)\\0&i\not=cnt(j)\end,g_=\beginb_j&i=cnt(j)\\0&i\not=cnt(j)\end

\]然後我們令,\(ans_i=\sum_^if_j*g_\),則\(c_i=ans_\)。

注意,這裡的\(*\)為\(fwt\)的或卷積,因此上式可以看作是卷積套卷積,只不過外層這個卷積\(n\le20\),完全無需優化而已。

#include#define tp template#define ts template#define reg register

#define ri reg int

#define con const

#define ci con int&

#define i inline

#define w while

#define n 20

#define x 1000000009

using namespace std;

int n,p,a[n+5][1<>1]+(i&1);//預處理每個數二進位制下1的個數

for(i=0;i^p;++i) f.read(a[g[i]][i]);for(i=0;i^p;++i) f.read(b[g[i]][i]);//讀入

for(i=0;i<=n;++i) fwt(a[i],1),fwt(b[i],1);for(i=0;i^p;++i)//先做dwt

for(j=0;j<=n;++j) for(k=0;k<=j;++k) ans[j][i]=(1ll*a[k][i]*b[j-k][i]+ans[j][i])%x;//求出ans陣列

for(i=0;i<=n;++i) fwt(ans[i],x-1);for(i=0;i^p;++i) f.write(ans[g[i]][i]);return f.clear(),0;//做idwt,輸出答案

}

luogu P6097 子集卷積 FST FWT

link 子集卷積 學了1h多 終於看懂是怎麼回事了 題解寫的不太清楚 翻了好幾篇部落格才懂 乙個需要用到的性質 二進位制位為1個數是i的二進位制數s 任意兩個沒有子集關係。挺顯然。而fst就是利用這個性質靠fwt做的。直接說做法 定義 f 表示 s 為i狀態為s的值.對於另乙個g陣列也同時定義。設...

洛谷 5826 模板 子串行自動機 題解

部落格觀賞效果更佳 你以為我只是單純的子串行自動機嗎?其實我是是子串行自動機 可持久化陣列噠!但是我看見乙個大神給出了乙個特別神仙又巧妙的思路!我不禁要寫一篇題解記錄下這神奇的思路!而且 賊短哦 比可持久化陣列好寫到不知道多少倍呢www 給定乙個序列a aa長度 1e5,還要一些要詢問的字串b bb...

洛谷 模板 樹狀陣列

如題,已知乙個數列,你需要進行下面兩種操作 1.將某乙個數加上x 2.求出某區間每乙個數的和 輸入格式 第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含3或4個整數,表示乙個操作,具體如下 操作...