bingxuan9112
Omelet >wO
簡單的乘法公式蘊含排列組合的意義
定義一個數列 ⟨an⟩的一般生成函數如下
(又稱形式幂級數、組合生成函數)
順便定義 xk 的係數是 F[xk]=ak
an∈F
聽說 F 要是一個 Field
還有這邊先不要管 x 收不收斂
加法減法應該不用解釋吧@@
可以想成 an 就代表「拿 n 個的方法數」
那如果現在有兩種物品,拿 n 個的方法數分別是 an,bn
那麼我們把他們乘在一起得到的多項式就代表總共拿了 n個的方法數
m(_ _)m
費式數列?
a0=0,a1=1,an=an−1+an−2
卡特蘭數
不同構的n個節點二元樹的數量
咦?我不會除法QQ
其中 α,β是分母的兩個根
review: 1−rx1=k=0∑∞rkxk
所以 F[xn]=Aαn+Bβn
微積分!
「惟天下之靜者乃能見微而知著。」
若f(x)(f)為一個函數,則將f的微分寫作f′。
微分代表
一個函數的斜率
(notation) dxdf 為
「若變化x的值一點點,那f會變化多少?」
(單項式微分)
(連鎖律)
(乘法)
(加法)
Note: f∘g=f(g)
若ai=i,請找出⟨ai⟩的生成函數?
所以(1−x)21即為所求!
若ai=i2,請找出⟨ai⟩的生成函數?
但是 還不夠耶
若ai=i2,請找出⟨ai⟩的生成函數?
只是需要一點巧思嘛!
「積土成山,風雨興焉;積水成淵,蛟龍生焉;積而算之,題AC焉」
若f為一個函數,則將f的積分寫作∫f。
積分代表
一個函數地下的面積
(單項式微分)
(分布積分)
(加法)
積分和微分互為反運算!
O(n) (trivial)
Point-Value representation
Coefficient representation
(a,f(a)),(b,f(b)),…(jizz,f(jizz))
f(x)=∑akxk
運算簡單
運算不簡單
推 >< by Sean
Point-Value representation
Coefficient representation
乃衣服:O(n2)
FFT:O(nlogn)
Definitions & Basic Properties
讀:n次原根的k次方
Problem Statement
現在,給定一個函數f(x)=k=0∑n−1akxk,請求(1,f(1)),(ωn,f(ωn),(ωn2,f(ωn2))…(ωnn−1,f(ωnn−1)?
矩陣表示法
以後,我們將假設n為2的冪次。若不是,則可以補零到是就好了。
TL;DR:n=2l
nlogn Speedup
f(x)=E(x2)+xO(x2)
假設O(x)=∑k=0a2k+1xk,E(x)=∑k=0a2kxk
nlogn Speedup
f(x)=E(x2)+xO(x2)
若O[k]=O(ω2nk),E[k]=E(ω2nk),所求f[k]=f(ωnk)
遞迴計算的結果
nlogn Speedup
nlogn Speedup
And then...
但是...
有了這堆東西...
除了炫耀還能幹嘛啊?
感覺還需要一個東西轉回去⋯⋯
Inverse FFT
還記得FFT有矩陣表示方式嗎:Aij=ωnij (0 base)
那可以證明,(A−1)ij=nωn−ij哦!
(i=j的時候是和為0的等比級數)
const double PI = acos(-1);
typedef complex<double> cd;
vector<cd> FFT(const vector<cd> &F, bool inv) { // assume F.size() == 2^k
if(F.size() == 1) return F; // base case (important)
vector<cd> rec[2];
for(int i = 0; i < F.size(); i++) rec[i&1].push_back(F[i]);
rec[0] = FFT(rec[0],inv);
rec[1] = FFT(rec[1],inv);
double theta = (inv ? 1 : -1) * 2 * PI / F.size();
cd now = 1, omega(cos(theta), sin(theta));
vector<cd> ans(F.size());
for(int i = 0; i < F.size()/2; i++) {
ans[i] = rec[0][i] + now * rec[1][i];
ans[i+F.size()/2] = rec[0][i] - now * rec[1][i];
now *= omega;
}
if(inv) for(int i = 0; i < ans.size(); i++) ans[i] /= 2;
return ans;
}
註:為求效率,也可以寫成迴圈版本,避免遞迴
const double PI = acos(-1);
typedef complex<double> cd;
void FFT(cd F[], int n, bool inv) { // in-place FFT, also assume n = 2^k
for(int i = 0, j = 0; i < n; i++) {
if(i < j) swap(F[i], F[j]);
// magic! (maintain j to be the bit reverse of i)
for(int k = n>>1; (j^=k) < k; k>>=1);
}
for(int step = 1; step < n; step <<= 1) {
double theta = (inv ? 1 : -1) * PI / step;
cd omega(cos(theta), sin(theta));
for(int i = 0; i < n; i += step*2) {
cd now(1,0);
for(int j = 0; j < step; j++) {
cd a = F[i+j];
cd b = F[i+j+step] * now;
F[i+j] = a+b;
F[i+j+step] = a-b;
now *= omega;
}
}
}
if(inv) for(int i = 0; i < n; i++) F[i] /= n;
}
Implement an operation that is equivalent to the operation DFTP, where DFT is the discrete Fourier transform.
一種方法是先取ln,乘上倍數後再exp
另一種方法則是
牛頓逼近法
結論:
A(x)=B(x)Q(x)+R(x)
設n=degA≥m=degB
則degQ=n−m,degR<m
當你想要考慮物件的順序的時候可以考慮「指數生成函數」
光維基上神奇的生成函數就好多 OAO
例如什麼跟數論函數有關的Lambert、Dirichlet之類的
理論上只要保證解析函數 μk(x)線性獨立
∑k=0∞akμk(x) 應該都可以拿來用吧(?)
例如 μk(x)=cos(kx) 之類的
以上言論若有錯誤不負責
取數個物品A和物品B,共取n個
排列順序不同算不同方式的方法數
可以知道題目就是要求有兩個環的排列
我們先考慮恰是一個環的排列,有 (n−1)! 種方法數
那麼從 n 個元素裡面選出 k 個分給第一個環,另外 n−k個分給第二個環,也就是
k∑(kn)(k−1)!(n−k−1)!
令 F=k=0∑n(k−1)!k!xk
所求就是 21F2
連講師都不會
By bingxuan9112