基 础 多 项 式 与 基 础 生 成 函 数

噔 噔 噔。
你说的对,但是确实挺基础的说。
很多东西避开了严谨的描述。
文章内容非常浅(che)显(dan)。
prework
卷积 :\(a,b\)为两个数列,两个数列的卷积 \(c\) 有 \(c_k=\sum\limits_{i=1}^{k} a_{i}b_{k-i}\)。
多项式的点值表示:\(n+1\) 个坐标确定一个 \(\le n\) 次的多项式,我们可以用这 \(n+1\) 个坐标表示。
注意到直接用点值表示出来的话,能快速的得到相乘的多项式的点值表示。
我们实际上是计算特殊的点值。
单位根:\(x^n-1 =0\) 我们称 \(x\) 为 \(n\) 次单位根,其中 $n \in \mathbb{C} $。我们设 $ \omega $,根据代数基本定理,它在复数集下显然有 \(n\) 个解。我们分别记最小解为 $ \omega_1,\omega_2,\omega_3 \ldots \omega_n$,实际上就是每个角为 \(\frac{2\pi}{n}\),这个东西定义为 \(\omega_{n} = e^{\frac{2\pi i}{n}}\)
等一下,你知不知道你在写什么,这个不就是三角函数直接就写出来了吗???
$ \because e^{i x } = \cos x+ i\sin x $(欧拉公式)
\(\therefore \omega_n = \cos \frac{2\pi}{n} + i\sin \frac{2\pi}{n}\)
FFT的推导过程
离散傅里叶变换(DFT)
是长这样的,\(a\)是一个数列,对于 \(0 \le k < n\),我们令
我们记 \(b=F(a)\)
离散傅里叶变换的逆变换(IDFT)
顾名思义,直接给出式子
证明有点长,大概就是根据定义去推。
意思就是说如果我们知道单位根的点值,就能推出原多项式的系数了。
循环卷积
有 \(a,b\) 两个数列,
\(c_k=\sum\limits_{i+j \bmod n=k} a_{i}b_{k-i}\)
我们记作 $ c = a * b$
我们有一个性质 \(F(a*b)=F(a) \times F(b)\)
补充单位根的两个性质
Lemma 1:\(({\omega_{2n}}^k)^2={\omega_{n}}^k\)
Lemma 2:\({\omega_{2n}}^{n+k}={\omega_{2n}}^{-k}\)
你把复平面建立出来证明式容易的。
我们对多项式 \(A(x)\) 开始进行操作,我们记 \(n=2m\)。
注意到有相同的,这是好事。
那我们定义\(A_0(x)=\sum\limits_{0\le i < m} a_{2i}x^{2i} ,A_1(x)= x\sum\limits_{0\le i < m} a_{2i+1}x^{2i}\)
蝴蝶变换
考虑将前面的东西结合一下?下面还是有 \(0 \le k < m\)
通过蝴蝶操作的过程可以看出,如果我们得到了 \(A_0(x),A_1(x)\)
在点\({\omega_{m}}^0,{\omega_{m}}^1 \ldots {\omega_{m}}^{m-1}\),我们可以在 \(O(n)\) 时间内
计算出 \(A(x)\) 在 \({\omega_{m}}^0,{\omega_{m}}^1 \ldots {\omega_{m}}^{m-1}\),我们可以在 \(O(n)\)处的点值。
而计算 \(A_0,A_1\) 的点值的过程可以递归分治进行。
根据主定理,我们可以在 \(O(n\log n)\) 的时间内求出所要的 \(A(x)\) 的点值表示。
为了快速的进行 IDFT,对比 DFT与 IDFT的表达式,可以发
现我们只需要将FFT过程中用到的 \(\omega_{n}\) 全部替换为  \({\omega_{n}}^{-1}\),最后再乘以 \(\frac{1}{n}\) 即可。
令 \(rev(x)\) 表示将 \(x\) 的二进制位的顺序反转之后得到的数字,我们每次 将 \(a_i = a_{rev(i)}\) 则每次需要对 \(a\) 进行的蝴蝶操作在 \(a′\) 中变成了对两个相邻的序列的操作。方便多了。我觉得你记忆模板就行。
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+6,bmod=1e9+7,INF=2e9;
// 省略了缺省源,想看找我要就行了
struct CP{
    db x,y;
    CP(db X=0.0,db Y=0.0){x=X,y=Y;}
    inline CP operator +(const CP &p){return CP(x+p.x,y+p.y);}
    inline CP operator -(const CP &p){return CP(x-p.x,y-p.y);}
    inline CP operator *(const CP &p){return CP(x*p.x-y*p.y,y*p.x+x*p.y);}
}f[N<<1],g[N<<1];
int rev[N<<1];
int n,m;
const db pi=acos(-1);
void FFT(CP *f,db opt){
    rep(i,0,n-1)  if(i<rev[i])    swap(f[i],f[rev[i]]);
    for(int p=2;p<=n;p<<=1){
        int len=(p>>1);
        CP wd(cos(2*pi/p),sin(2*pi/p)*opt);
        static CP w[N];
        w[0]={1,0};
        rep(i,1,len)    w[i]=w[i-1]*wd;
        for(int k=0;k<n;k+=p){
            rep(l,k,k+len-1){
                CP now=f[l+len]*w[l-k];
                f[l+len]=f[l]-now,f[l]=f[l]+now;
            }
        }
    }
}
int main(){
    cin>>n>>m;
    rep(i,0,n)  cin>>f[i].x;
    rep(i,0,m)  cin>>g[i].x;
    for(m+=n,n=1;n<=m;n<<=1);
    rep(i,0,n)  rev[i]=(rev[i>>1]>>1)|((i&1)?(n>>1):0);
    FFT(f,1);FFT(g,1);
    rep(i,0,n)  f[i]=f[i]*g[i];
    FFT(f,-1);
    rep(i,0,m)  cout<<(int)(fabs(f[i].x)/(n*1.0)+0.5)<<" ";
}
NTT
一些定义
阶:对于正整数 \(m,a\),满足 \(\gcd(a,m)=1\), 使得 \(a^{n} \equiv 1 (\bmod m)\),则最小的正整数 \(n\) 称为 \(a\) 模 \(m\) 的阶,记作\(\delta_{m}(a)\)。
原根:如果$\delta_{m}(a) =\varphi(m) $,则 \(a\) 是 m 的一个原根。只有模\(2\),\(4\),\(p^a\),\(2p^a\) 存在原根。
upd:这个定义并不直接,有一个定义是满足 \(g^0,g^1,g^2 \dotsb,g^{\varphi(n)}\) 两两不同,则最小的 \(g\) 就是 \(\bmod n\) 意义下的原根。
设 \(m > 1\),\(g\) 为正整数且 \(gcd(g,m) = 1\)。则 \(g\) 是 \(m\) 的原根当且仅当对于任意 \(\varphi(m)\) 的质因子 \(q_i\),有 \(g^{\frac{\varphi(m)}{q_i}} \not\equiv 1 (\bmod \ m)\)。
暴力找是对的,量级是 \(O(n^{0.25})\)
这里并没有其他内容,后面再补吧。
假设质数 \(p\) 满足 \(p = r \times 2^x + 1\),\(g\) 是 \(p\) 的原根
使用 $g^{\frac{p-1}{n}} $ 带替之前的 \(\omega\),就是 NTT 了。证明略了。
这里应该有一张原根表。
分治FFT/NTT
分治 + FFT,洛谷板子也差不多,略。
全家桶
你好,这个是不是有点不太基础了。
多项式牛顿迭代
有一多项式\(g(x)\),一形式幂级数\(f(x)\),如果有 \(g(f(x))\equiv 0 (\bmod \ x^{n})\),那我们有
接下来都是默认在模意义下的。
证明需要使用泰勒展开,我们首先有 \(g(f0(x))\equiv 0 (\bmod \ x^{n})\)
实际上第三项之后就是 \(0\),所以
变形可以得到
实际上证明并不重要,接下来才是好玩的。
多项式求逆(乘法逆)
有多项式 \(h(x)\),若\(f(x)h(x) \equiv 1(\bmod \ x^n)\),\(f(x)\) 为 \(h(x)\) 的乘法逆。
设多项式\(G(x)\),\(G(f(x))=\frac{1}{f(x)} -h(x)\)
套公式得$ f(x) = f_0(x) - \frac{G(f_0(x))}{G'(f_0(x))}$,然后 \(f(x) = f_0(x) - \frac{\frac{1}{f_0(x)} -h(x)}{-\frac{1}{{f_{0}(x)}^2}}\)
得到结论 $ f(x) \equiv f_0(x) - {f_0}^2(x)h(x) \ (x \bmod \ x^{2n})$
继续咕咕。
不用咕咕了,剩下的没前途。
拉格朗日插值
这个倒是有点用。
暴力高斯消元是 \(O(n^3)\) 的。还会爆精度。
但注意到一点:我们只需弄出一个函数,让他满足我们给定的取值,再把需要的取值带进去就行了,所以是
其中
我们只要构造
\(
    f_i(x)=\prod\limits_{j \not ={i}} ^{j=n}\dfrac{x-x_j}{x_i-x_j}
\)
带入原式即可,正确性显然。
拉格朗日求系数:0
生成函数
咕咕,这个要有用一些。
一些题目
题目先咕咕了,后面来写,可能会重开一篇。
P1919 【模板】高精度乘法 | A*B Problem 升级版
注意到高精度乘法本身就是一个卷积,直接把每一位当系数卷积即可,要处理一下进位。
P3723 [AH2017/HNOI2017] 礼 物
题目是搞笑的,笔者看错题了,笔者更搞笑。
我们考虑一下增量为 \(\Delta\) 会发生什么。
\(\sum\limits_{i=1}^n=(x_i-y_i+\Delta)^2 = \sum\limits_{i=1}^n({x_i}^2+{y_i}^2-2x_iy_i-2\Delta(x_i-y_i) +\Delta^2)= \sum\limits_{i=1}^n({x_i}^2+{y_i}^2 )-\sum\limits_{i=1}^n2x_iy_i-2\Delta\sum\limits_{i=1}^n(x_i)-\sum\limits_{i=1}^n(y_i)+n\Delta^2\)
枚举 \(\Delta\),只有 \(\sum\limits_{i=1}^n2 x_i y_i\) 不是定值。
考虑怎么求这个东西的最值,如果没有题目上的限制的话是P1966[NOIP2013 提高组] 火柴排队,我们设它旋转了 \(k\) 次 ,第 \(k\) 次的和就是 \(\sum\limits_{i=1}^n2 x_{i+k +[i+k>n] \times -1} y_i\) 确实太不好看了,断环为链,倍长出去就是 \(\sum\limits_{i=1}^n2 x_{i+k } y_i\)
经典Trick,直接翻转 \(x\),得到\(\sum\limits_{i=1}^n2 x_{2n-i-k } y_i\),这个就是卷积啊,答案就在 \(n+1\) 到 \(2n\) 之间的最值。那么就做完了。
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号