[基本操作]多项式

首先 FFT

没啥可说的,背诵全文

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 4000100,mod = 998244353,iG = 332748118,G = 3;
int n,L,R[maxn],lg[maxn + maxn];
int poly[maxn],Poly[maxn];
int nn;
inline int read()
{
    int x = 0,f = 1;char ch = getchar();
    for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
    for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
    return x * f;
}
inline int ksm(int x,int t)
{
    int res = 1;
    while(t)
    {
        if(t & 1) res = ((LL)res * (LL)x) % mod;
        x = ((LL)x * (LL)x) % mod;
        t >>= 1;
    }
    return res;
}
inline void fft_init(int n){for(int i=0;i<n;i++) R[i] = (R[i>>1] >> 1) | ((i & 1) << (lg[n] - 1));}
inline void fft(int *a,int f,int n)
{
    for(int i=0;i<n;i++)if(i < R[i])swap(a[i],a[R[i]]);
    for(int i=1;i<n;i<<=1)
    {
        int wn = ksm(((f == 1) ? G : iG),(mod - 1) / (i << 1));
        for(int j=0;j<n;j+=(i<<1))
        {
            int w = 1;
            for(int k=0;k<i;k++,w=(1LL * (LL)w * (LL)wn) % mod)
            {
                int x = a[j + k], y = (1LL * (LL)w * (LL)a[j + k + i]) % mod;
                a[j + k] = (x + y) % mod;
                a[j + k + i] = (x - y + mod) % mod;
            }
        }
    }
    if(f == -1)
    {
        int inv = ksm(n,mod - 2);
        for(int i=0;i<n;i++)a[i] = ((LL)a[i] * (LL)inv) % mod;
    }
}
int main()
{
    n = read();nn = read();lg[0] = -1;
    for(int i=1;i<maxn+maxn;i++)lg[i] = lg[i >> 1] + 1;
    for(int i=0;i<=n;i++)poly[i] = read();
    for(int i=0;i<=nn;i++)Poly[i] = read();
    int m;
    for(m=n+nn,n=1;n<=m;n<<=1);
    fft_init(n);
    fft(poly,1,n);fft(Poly,1,n);
    for(int i=0;i<n;i++)poly[i] = ((LL)poly[i] * (LL)Poly[i]) % mod;
    fft(poly,-1,n);
    for(int i=0;i<=m;i++)printf("%d ",poly[i]);
}
NTT
#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read()
{
    int x = 0,f = 1;char ch = getchar();
    for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
    for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
    return x * f;
}
const int maxn = 4e6 + 10;
const double pi = acos(-1);
#define cp complex<double>
cp a[maxn],b[maxn];
int lg[maxn + maxn],R[maxn];
inline void fft_init(int n){for(int i=0;i<n;i++)R[i] = (R[i >> 1] >> 1) | ((i & 1) << (lg[n] - 1));}
inline void fft(cp *a,int f,int n)
{
    for(int i=0;i<n;i++)if(i < R[i])swap(a[i],a[R[i]]);
    for(int i=1;i<n;i <<= 1)
    {
        cp wn(cos(pi / i),f * sin(pi / i));
        for(int j=0;j<n;j += (i << 1))
        {
            cp w(1,0);
            for(int k=0;k<i;k++,w *= wn)
            {
                cp x = a[j + k],y = w * a[j + k + i];
                a[j + k] = x + y;
                a[j + k + i] = x - y;
            }
        }
    }
    if(f == -1)for(int i=0;i<=n;i++)a[i] /= n;
}
int main()
{
    lg[0] = -1;for(int i=1;i<maxn+maxn;i++)lg[i] = lg[i >> 1] + 1;
    int N = read(),M = read();
    for(int i=0;i<=N;i++)cin>>a[i];
    for(int i=0;i<=M;i++)cin>>b[i];
    int n;
    for(n=1;n <= N+M;n<<=1);
    fft_init(n);fft(a,1,n);fft(b,1,n);
    for(int i=0;i<=n;i++)a[i] *= b[i];
    fft(a,-1,n);
    for(int i=0;i<=N+M;i++)printf("%d ",(int)(a[i].real() + 0.5));
}
FFT

多项式的一个基本操作就是卷积,也就是对于两个多项式 $F$ 和 $G$ ,求

$$\sum_{i=1}^n F_i \times G_{n-i}$$

很多 dp 题可以转换成卷积的形式,我们可以 FFT 一发

对于一些计数问题,生成函数是一个非常有用的计数方法,FFT 也可以快速计算两个母函数的卷积

之后就是一些很好的操作,先放在这

1.求逆

扫描二维码关注公众号,回复: 4461379 查看本文章

对于一个多项式 $A$ ,你要求一个多项式 $B$ 满足 $A \times B \equiv 1 \space (mod \space x^n)$

猜你喜欢

转载自www.cnblogs.com/Kong-Ruo/p/10101761.html
今日推荐