有的多项式题不需要用到 (O(nlog n)) 的多项式全家桶,所以来写下递推的 (O(n^2)) 做法。
多项式求逆
设 (B(x)) 是 (A(x)) 的逆,那么:
[egin{aligned}B(x)A(x)&=[n==0]\sum_{i=0}^nA_iB_{n-i}&=0(n>0),B_0=frac{1}{A_0}(n=0)\B_n&=-frac{1}{A_0}sum_{i=1}^nA_iB_{n-i}end{aligned}
]
Code
void INV(int *a,int *ans,int n)
{
for (int i = 0;i <= n;i++)
ans[i] = 0;
ans[0] = mypow(a[0],p - 2);
for (int i = 1;i <= n;i++)
{
for (int j = 1;j <= i;i++)
ans[i] -= 1ll * a[j] * ans[i - j] % p,ans %= p;
ans[i] = 1ll * ans[i] * ans[0] % p;
}
}
多项式快速幂
设 (B(x)=A^k(x)) ,那么:
[egin{aligned}B'(x)&=kA'(x)A^{k-1}(x)\B'(x)A(x)&=kA'(x)B(x)\sum_{i=0}^nB'_iA_{n-i}&=ksum_{i=0}^nA'_iB_{n-i}\sum_{i=0}^nB_{i+1}(i+1)A_{n-i}&=ksum_{i=0}A_{i+1}(i+1)B_{n-i}\B_{n+1}=frac{k}{A_0(n+1)}&(sum_{i=0}^nA_{i+1}(i+1)B_{n-i}-sum_{i=0}^{n-1}B_{i+1}(i+1)A_{n-i})end{aligned}
]
边界 (B_0=A_0^k)
Code
void Polypow(int *a,int *ans,int n,int k)
{
for (int i = 0;i <= n;i++)
ans[i] = 0;
int st = 0,sst = 0;
while (!a[st])
st++;
sst = st;
st = min(st * k - 1,n);
if (st == n)
return;
st++;
ans[st] = mypow(a[sst],k);
int inv = mypow(a[sst],p - 2);
for (int i = 1;i <= n - st;i++)
{
for (int j = 0;j < i;j++)
ans[i + st] += 1ll * k * a[j + 1 + sst] % p * (j + 1) % p * ans[i - 1 - j + st] % p,ans[i + st] %= p;
for (int j = 0;j < i - 1;j++)
ans[i + st] -= 1ll * a[i - 1 - j + sst] * ans[j + 1 + st] % p * (j + 1) % p,ans[i + st] %= p;
ans[i + st] = 1ll * ans[i + st] * inv % p * Inv[i] % p;
}
}
Ln
设 (B(x)=ln(A(x))) ,那么有 (B'(x)=frac{A'(x)}{A(x)}) ,那么:
[egin{aligned}A'(x)&=B'(x)A(x)\A'_n&=sum_{i=0}^nA_iB'_{n-i}\A_{n+1}(n+1)&=sum_{i=0}^nA_iB_{n-i+1}(n-i+1)\B_{n+1}&=frac{1}{n+1}(A_{n+1}(n+1)-sum_{i=1}^nA_iB_{n-i+1}(n-i+1))end{aligned}
]
要求 (A_0=1) ,边界 (B_0=0) 。
Code
void Ln(int *a,int *ans,int n)
{
for (int i = 0;i <= n;i++)
ans[i] = 0;
for (int i = 1;i <= n;i++)
{
ans[i] = 1ll * a[i] * i % p;
for (int j = 1;j < i;j++)
ans[i] -= 1ll * a[j] * ans[i - j] % p * (i - j) % p,ans[i] %= p;
ans[i] = 1ll * ans[i] * Inv[i] % p;
}
}
exp
设 (B(x)=e^{A(x)}) ,那么:
[egin{aligned}B'_n&=sum_{i=0}^nB_iA_{n-i}\B_{n+1}&=frac{1}{n+1}sum_{i=0}^nB_iA_{n-i+1}(n-i+1)end{aligned}
]
要求 (A_0=0) ,边界 (B_0=1) 。
Code
void exp(int *a,int *ans,int n)
{
for (int i = 0;i <= n;i++)
ans[i] = 0;
ans[0] = 1;
for (int i = 1;i <= n;i++)
{
for (int j = 0;j < i;j++)
ans[i] += 1ll * ans[j] * a[i - j] % p * (i - j) % p,ans[i] %= p;
ans[i] = 1ll * ans[i] * Inv[i] % p;
}
}
kexp
设 (B(x)=sum_{i=0}^kfrac{A^i(x)}{i!}) ,那么:
[egin{aligned}B'(x)&=sum_{i=0}^kfrac{{A^i}'(x)}{i!}\B'(x)&=sum_{i=0}^kfrac{A^{i-1}(x)iA'(x)}{i!}\B'(x)&=A'(x)(B(x)-frac{A^k(x)}{k!})end{aligned}
]
设 (C(x)=frac{A^k(x)}{k!}) ,可以通过多项式快速幂求出,然后就有:
[egin{aligned}B'(x)&=A'(x)(B(x)-C(x))\B'_{n}&=sum_{i=0}^nA'_{i}(B_{n-i}-C_{n-i})\B_{n+1}&=frac{1}{n+1}sum_{i=0}^nA_{i+1}(i+1)(B_{n-i}-C(n-i))end{aligned}
]
Code
void kexp(int *a,int *ans,int n,int k)
{
int inv = 1,res = 1;
for (int i = 1;i <= k;i++)
inv = 1ll * inv * i % p;
inv = mypow(inv,p - 2);
Polypow(a,tmp,n,k);
for (int i = 0;i <= n;i++)
tmp[i] = 1ll * tmp[i] * inv % p;
for (int i = 0;i <= n;i++)
ans[i] = 0;
ans[0] = 1;
for (int i = 1;i <= k;i++)
{
res = 1ll * res * a[0] % p * Inv[i] % p;
ans[0] += res;
ans[0] %= p;
}
for (int i = 1;i <= n;i++)
{
for (int j = 0;j < i;j++)
ans[i] += 1ll * a[j + 1] * (j + 1) % p * ((ans[i - j - 1] - tmp[i - j - 1]) % p) % p,ans[i] %= p;
ans[i] = 1ll * ans[i] * Inv[i] % p;
}
}