学习资料:
王乐平、策爷冬令营讲义。
多项式技巧
牛顿迭代(泰勒展开)
很多时候推式子就是取对数、积分,exp和泰勒展开的结合
泰勒展开在mod xn意义下只需要保留前n项,性质非常优美。
而插值,对于一个k次的多项式,必须要k + 1个值的代入,如果只求该多项式的前n项,也不能只用
n + 1个点代入
这是一篇非常好的博客。特别是把所有多项式操作都用泰勒展开推导,以后就不用再死记,也不用担心推错了!from yyb
复合逆
注意当f(x)本身不存在逆元的时候,可以求f(x) / x的逆元
否则(x / f(x))n 的第n - 1
项为0
例题
直接推生成函数
【BZOJ3625】小朋友和二叉树
from cz_xuyixuan
注意这道题是普通生成函数,不是指数型生成函数
代码只有main函数,多项式模板在下面
int n,m;
vector <int> fact,inv_fact;
vector <int> f,g,h,tmp;
void pre_calc(){
// g[0] = 1;
rep(i,0,m){
// g[i] = mul(g[i],inv_fact[i]);
sub(f[i],mul(g[i],4));
// cout<<f[i]<<" ";
}
f[0] = 1;
// cout<<endl;
f = sqrt(f);
add(f[0],1);
f = inverse(f);
rep(i,0,m) f[i] = mul(f[i],2);
}
int main(){
scanf("%d %d",&n,&m);
f.resize(m + 1) , g.resize(m + 1);
rep(i,1,n){
int x;
scanf("%d",&x);
if ( x <= m ) g[x]++;
}
pre_calc();
rep(i,1,m){
// f[i] = mul(f[i],fact[i]);
printf("%d\n",f[i]);
}
}
bzoj 3684 大朋友和多叉树
复合逆裸题。
注意F(x) / x才可以求逆
int n,m;
poly fact,inv_fact;
poly f,g,h,tmp;
void pre_calc(){
add(g[0],1);
g = inverse(g);
g = power(g,n);
int ans = mul(power(n,mod - 2),g[n - 1]);
cout<<ans<<endl;
}
int main(){
scanf("%d %d",&n,&m);
f.resize(n + 1) , g.resize(n + 1);
rep(i,1,m){
int x;
scanf("%d",&x);
g[x - 1] = mod - 1;
}
pre_calc();
}
多项式模板
注意事项:
求导和积分多项式的次数变化
开根号如果常数项不为完全平方数,需要用二次剩余开根号的模板。详见或这位大佬
求逆常数项不能为0 , 否则不存在逆元
special thanks to wxh010910
#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
#define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
#define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
#define forup(i,l,r) for (register int i = l ; i <= r ; i += lowbit(i))
#define fordown(i,id) for (register int i = id ; i ; i -= lowbit(i))
#define pb push_back
#define prev prev_
#define stack stack_
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-(x)))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pr;
const int maxn = 200020;
typedef vector <int> poly;
const int mod = 950009857;
//NOTES: 任意乘法需要用mul,或者强制用long long。
//注意取模
//====================================basic operation===============================
inline void add(int &x, int y) {
x += y;
if (x >= mod) {
x -= mod;
}
}
inline void sub(int &x, int y) {
x -= y;
if (x < 0) {
x += mod;
}
}
inline int mul(int x, int y) {
return (int) ((long long) x * y % mod);
}
inline int power(int x, int y) {
int res = 1;
while (y) {
if (y & 1) {
res = mul(res, x);
}
x = mul(x, x);
y >>= 1;
}
return res;
}
inline int inv(int a) {
int b = mod, u = 0, v = 1;
while (a) {
int t = b / a;
b -= t * a;
swap(a, b);
u -= t * v;
swap(u, v);
}
if (u < 0) {
u += mod;
}
return u;
}
//=============