題目傳送門
給出\(n,t,x,y,z\),值域\(\le 2^t\),給出\(n\)個三元組\((a_i,b_i,c_i)\),表示有\(x\)個\(a_i\),\(y\)個\(b_i\),\(z\)個\(c_i\)。對於每個\(k\in [0,2^t-1]\),求出從每組選出乙個數的異或值為\(k\)的方案數。
先定義\([\delta ^n]f(\delta)\)表示多項式\(f\)的第\(n\)位係數。
不得不說,這道題真的很妙。而且也加深了我對fwt的理解。
如果我們對每個三元組建立生成函式為:
\[f_i(\delta )=x\delta^+y\delta^+z\delta ^
\]那麼對於\(k\)的答案就是:
\[[\delta^k]\prod_^ f_i(\delta)
\]這裡的乘法定義為異或卷積,就是\([\delta^n]f(\delta) g(\delta)=\sum_ [\delta^i] f(\delta) [\delta^j] g(\delta)\)。
可以看出來,上面這個式子可以使用\(\text \)進行優化,但是\(\theta(nk2^k)\)的時間複雜度顯然通過不了這道題。
但是這道題十分特殊,因為每個多項式只有\(3\)個點有值。於是,我們可以考慮在\(\text \)的過程中進行優化。
我們可以考慮到,對於\([\delta^i]fwt(f_n)\)有
\[[\delta^i]fwt(f_n)=(-1)^x+(-1)^y+(-1)^z
\]其中,\(cnt(i)\)表示\(i\)在二進位制下\(1\)的個數。
如果我們按照上面的構造的話,時間複雜度雖然降為\(\theta((n+k)2^k)\),但是仍然無法通過。
但是我們發現對於\([\delta^i]fwt(f_n)\),它的值只可能有\(8\)種,形式為\(x+y+z,x+y-z,...\)。於是,我們可以自然地想到一種方法,即計算對於\([\delta ^i]\prod fwt(f_n)\)每一種出現了多少次,然後直接快速冪即可。
但是\(8\)種顯然太多了,我們可以通過把乙個三元組\((a_i,b_i,c_i)\)變為\((0,b_i\otimes a_i,c_i\otimes a_i)\),最後答案再異或上\(\otimes_^ a_i\)。這樣我們就只有\(4\)種情況了。
為了方便,我們設\(s =\prod_^ fwt(f_i)\)。這裡的乘法就是\([\delta^i]f(\delta) g(\delta) =[\delta^i]f(\delta) [\delta^i]g(\delta)\)。我們對於\([\delta^i]s\)可以設\(c1,c2,c3,c4\)表示:
\[[\delta^i]s=(x+y+z)^ (x+y-z)^(x-y+z)^(x-y-z)^
\]於是,我們的目標就是通過設立\(4\)個本質不同的一次方程解出\(c1,c2,c3,c4\)。
首先,非常顯然:
\[c1+c2+c3+c4=n\ \ \ \ \ \ \ \ \ \ \ (1)
\]然後呢?我們發現其實\(c1,c2,c3,c4\)跟\(x,y,z\)其實半毛錢都沒有,於是我們可以對\(x,y,z\)代入特定值解出\(c1,c2,c3,c4\)。
這樣,我們就可以得到:
\[\sum_^ fwt(f_j)[\delta^i]=p1=c1+c2-c3-c4\ \ \ \ \ \ \ \ \ (2)
\]非常顯然,你把\(x=0,y=1,z=0\)帶進去就好了。
與上面一樣,我們可以得到:
\[\sum_^ fwt(f_j)[\delta ^i]=p2=c1-c2+c3-c4\ \ \ \ \ \ (3)
\]但是我們現在似乎只有\(3\)個方程。。。蛤?你說\(x=1,y=0,z=0\),顯然它與\((1)\)式本質相同。
於是,我們現在需要一點大大的腦洞。
我們發現這種情況其實就是上面兩種情況的卷積,就可以得到:
\[[\delta^i] fwt(f_k)=(-1)^(-1)^
\]於是,我們可以得到:
\[\sum_^ fwt(f_k)[\delta^i]=p3=c1-c2-c3+c4\ \ \ \ \ \ (4)
\]於是,我們就可以得到:
\[\left\
c1+c2+c3+c4=n\\
c1+c2-c3-c4=p1\\
c1-c2+c3-c4=p2\\
c1-c2-c3+c4=p3
\end\right.\]
\[\rightarrow \left\
c1=\frac\\
c2=\frac\\
c3=\frac\\
c4=\frac
\end\right.
\]於是,我們就可以在\(\theta(n+k2^k)\)時間內解決。
#include using namespace std;
#define int register int
#define inv2 499122177
#define mod 998244353
#define int long long
template inline void read (t &t)while (c >= '0' && c <= '9') t *= f;}
template inline void read (t &t,args&... args)
template inline void write (t x)if (x > 9) write (x / 10);putchar (x % 10 + '0');}
int quick_pow (int a,int b)
return res;
}int inv (int x)
int n,t,lim,f[1 << 17],f1[1 << 17],f2[1 << 17],f3[1 << 17];
void dwt (int *a)
}void idwt (int *a)
}signed main()
idwt (f);
for (int i = 0;i < lim;++ i) write ((f[i ^ sta] + mod) % mod),putchar (' ');
putchar ('\n');
return 0;
}
PAT甲級題解 1119
根據前序和後序來確定中序是否是唯一的 如果乙個數他在根結點旁邊 那麼就無法判斷它是否是左右子樹 這個時候就得重新考慮了 include using namespace std const int maxn 50 struct node bool flag true vector int in int...
CF1119H Triple 西行寺無餘涅槃
現在有 n 個物品,同時有 k 種屬性,每個屬性有其價值 w i 每個物品的一種屬性對應乙個權值 a in 0,2 m 現在對於 0,2 m 中的每個 x 求出 sum limits left oplus n a x right prod n w n le 10 5,m le 16,m k le 2...
題解 CF1485 簡要題解
奇怪的難度。當 b 2 的時候再操作,操作次數是一定的。因此 b 的變化量很小,暴力列舉。考慮哪個數不同,然後不同後可以選擇的區間是什麼。會發現中間夾著的區間選兩遍,旁邊的選一遍。做字首和好了。簡單轉化發現一定要滿足 a k b 1 k。列舉 b 貢獻式帶有乙個 min 找到其分割點,前一部分直接求...