多項式學習筆記

2022-05-19 20:22:14 字數 3576 閱讀 7140

太菜了並不是很理解多項式,簡單記錄一下,緩慢更新吧……

有問題問快速航

首先我們要求的柿子長這樣:

\[c(k) = \sum_a(i)*b(j)

\]大概思路:先把兩個多項式轉成點值\((dft)\),再把兩個多項式的點值乘在一起,把新的點值轉成多項式\((idft)\)即可

首先要了解複數的運算

\[(a + b*i) +(c+d*i) = (a+c)+(b+d)*i

\]\[(a + b*i) -(c+d*i) = (a-c)+(b-d)*i

\]\[(a + b*i) *(c+d*i) = (a*c - b*d)+(a*d+b*d)*i

\]隨便說下單位圓/單位根:

現在我們要把圓平分成\(n\)個,每乙個的大小應該是\(cos(2 π /n), sin(2π / n)\)

步入正題,具體操作長這樣:

\[f(x) = a_0*x^0+a_1*x^1+a_2*x^2+……+a_n*x^n

\]設\(f1(x) = a_0*x^0+a_2*x^1+……+a_*x^}\),\(f2(x) = a_1*x^0+a_3*x^2+……+a_*x^}\)

\[f(x) = f1(x^2)+x*f2(x^2)

\]現在我們只需要知道\(f1(x), f2(x)\)就可以知道\(f(x)\)了,於是我們可以遞迴處理(所以我們需要保證多項式的項數為\(2^x\))

把單位根帶到上述式子裡面去,我們有:

\[f(w_n^x) = f1(w_n^)+w_n^x*f2(w_n^)

\]現在我們需要單位根的第一條性質(帶到單位圓上就知道了):

\[w_^ = w_^x

\]順便介紹性質二(還是畫畫圖就知道了):

\[w_^} = -w_^x

\]通過性質一,我們可以把柿子化成:

\[f(w_n^x) = f1(w_}^)+w_n^x*f2(w_}^)

\]由於我們只知道\(f1(x), f2(x)\)的\(0-\frac\)的所有點值要求出\(f(x)\)的\(0-n\)的所有點值

分類討論一下:

如果\(x<\frac\),直接用\(f1,f2\)的值就行

如果\(x≥\frac\),不妨設\(x=x+\frac\)

\[f(w_n^}) = f1((w_^})^2)+w_n^}*f2((w_^}})^2)

\]由於第二條性質

\[f(w_n^}) = f1((-w_^x)^2)-w_n^*f2((-w_^)^2)

\]\[f(w_n^x) = f1(w_}^)-w_n^x*f2(w_}^)

\]發現只有乙個符號的區別

我們假設我們通過\(dft\)求出了點值為\(a_0, a_1……, a_n\),最後我們要求出的值為\(a_0, a_1……, a_n\)

其實我們只要解乙個這樣的方程組:

\[a_0*(w_n^0)^0+a_1*(w_n^0)^1+a_2*(w_n^0)^2+……+a_n*(w_n^0)^2

\]\[a_0*(w_n^1)^0+a_1*(w_n^1)^1+a_2*(w_n^1)^2+……+a_n*(w_n^1)^2

\]\[……

\]\[a_0*(w_n^)^0+a_1*(w_n^)^1+a_2*(w_n^)^2+……+a_n*(w_n^)^2

\]這就是乙個矩陣形式了

第乙個矩陣是所有的\((w_n^x)^k\),我們計為矩陣v,第二個矩陣為所有的\(a_x\)計為a,第三個矩陣為所有的\(a_x\)計為a

於是我們的柿子變成了\(a*v=a\)

如果我們知道\(v^\),那麼我們有\(a*v^ = a\),a即為所求

現在考慮求逆:

我們需要介紹性質三:\(\sum_^(w_n^k)^j=[k==0]*n\)

證明其實不難,畫畫圖就好了,我們要求的柿子為:\(\sum_^(w_n^k)^j\)

如果\(k =0\),那麼原式\(=\sum_^ = n\)

如果\(k≠0\),記\(s=\sum_^(w_n^k)^j\)

\(s*w_n^k = \sum_^(w_n^k)^j =s-1+(w_n^k)^n = s\)

因為\(w_n^k≠0\),所以\(s=0\)

我們令\(v^(i, j) = (w_n^)^j\)

所以\((v*v^)(i, j)=\sum_^(w_n^)^k*(w_n^k)^j=\sum_^(w_n^)^k\)

根據性質三,當\(i=j\)時\((v*v^)(i, i)=n\),否則\(=0\),只需要把每一項\(/n\)即可

然後我們有發現,只需要把\(a\)看成新的係數,把所有的\((w_n^j)^k\)看成\((w_n^)^k\),那麼就是一邊新的\(dft\)了

所以唯一的差別就是單位根前面乘了乙個\(-1\)即可

struct node a[maxn], b[maxn];

il node operator + (node a, node b) ;}

il node operator - (node a, node b) ;}

il node operator * (node a, node b) ;}

int n, m, lim;

il void fft(node *x, int f, int len) , base = (node);

for(re int i = 0; i < (len >> 1); ++ i, w = w * base)

}int main()

講講迭代版的\(fft\)

通過打表發現:乙個數x再最後一次出現的位置\(r[i]\)是可以通過公式算出來的:\(r[i] = (r[i >> 1] >> 1)\ |\ ((i\ \&\ 1) << (lim - 1))\)

然後我們在\(fft\)前面把x交換到對應位置,然後用類似上述方法乙個個合併即可(我不是懶,是怕東西太多頁面卡)

il void fft(node *x, int f, int len) ;

for(re int p = mid * 2, j = 0; j < len; j += p) ;

for(re int k = 0; k < mid; ++ k, w = w * base)

} }

}rep(i, 0, (1 << lim)) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lim - 1));

大概就是你把原根看成單位根,然後跑\(fft\)即可(我不是懶,是怕東西太多頁面卡)

#define mod 998244353

#define invg 332748118

#define g 3

#define maxn 10000006

int n, m, a[maxn], b[maxn], l, lim = 1, r[maxn];

il int qpow(int a, int b)

return r;

}il void ntt(int *x, int f, int len)

} }}signed main()

不會

不會不會

不會不會

不會不會

不會不會

不會

學習筆記 多項式

給你n個點 x 1,y 1 x 2,y 2 求乙個n 1次的多項式 f x 求 f k 我們可以認為 f x f 1 x f 2 x f x 其中 f i x i y i 且 forall j neq i,f i x j 0 也就是說乙個點 x i 只在乙個函式中為 y i 其他函式中均為0 換言之...

學習筆記 多項式

把一直學不懂的各種大常數 o n log n 的神奇多項式演算法總結一下 證明什麼的比較簡略 還有我今天才知道預處理一下單位根會快很多 qwq 最沒用的乙個 首先我們能寫出乙個 o n 2 的暴力 這個你都不會就可以退役了 某位dalao題解中的 要確定乙個多項式,我們發現只要代 f 1 f 2 f...

多項式 學習筆記

已知兩個多項式的係數表示式,求其乘積的係數表示式。c n sum limits a ib 係數表示式逐項相乘,複雜度 o n 2 而點值表示式相乘複雜度為 o n 因此我們要快速地將兩個多項式轉化為點值表示式,完成點值表示式的乘法,然後轉為係數表示式得到結果。表示式轉換的過程分別是離散傅利葉變換 d...