• 洛谷 P3803 多项式乘法


    题目背景

    这是一道FFT模板题

    题目描述

    给定一个n次多项式F(x),和一个m次多项式G(x)。

    请求出F(x)和G(x)的卷积。

    输入输出格式

    输入格式:

    第一行2个正整数n,m。

    接下来一行n+1个数字,从低到高表示F(x)的系数。

    接下来一行m+1个数字,从低到高表示G(x))的系数。

    输出格式:

    一行n+m+1个数字,从低到高表示F(x)∗G(x)的系数。

    输入输出样例

    输入样例#1: 
    1 2
    1 2
    1 2 1
    输出样例#1: 
    1 4 5 2

    说明

    保证输入中的系数大于等于 0 且小于等于9。

    对于100%的数据: n, m leq {10}^6n,m106, 共计20个数据点,2s。

    数据有一定梯度。

    空间限制:256MB

    NTT和FFT有惊人的类似度hhh,总的说就是把单位根换成了原根。

    最好是取一个形如p=k*2^x+1这样的质数p,这里x最好大一点。

    然后在FFT里1的K次单位根是(cos(2*π/K),sin(2*π/K))  (一个复数),而NTT里则是 g^((p-1)/K)。

    dft的逆函数的话也类似,就是把g换成g^-1。

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 3000005
    #define ha 998244353
    using namespace std;
    const int ba=3;
    const int ni=ha/ba+1;
    
    inline int add(int x,int y){
        x+=y;
        if(x>=ha) x-=ha;
        return x;
    }
    
    inline int dec(int x,int y){
        x-=y;
        if(x<0) x+=ha;
        return x;
    }
    
    inline int ksm(int x,int y){
        int an=1;
        for(;y;y>>=1,x=(ll)x*x%ha) if(y&1) an=(ll)an*x%ha;
        return an;
    }
    
    int n,m,a[maxn],b[maxn];
    int r[maxn],l,inv;
    
    inline void fft(int *c,int f){
        for(int i=0;i<n;i++) if(i<r[i]) swap(c[i],c[r[i]]);
        
        for(int i=1;i<n;i<<=1){
            int omega=(f==1?ksm(ba,(ha-1)/(i<<1)):ksm(ni,(ha-1)/(i<<1)));
            for(int j=0,p=i<<1;j<n;j+=p){
                int now=1;
                for(int k=0;k<i;k++,now=(ll)now*omega%ha){
                    int x=c[j+k],y=(ll)now*c[j+k+i]%ha;
                    c[j+k]=add(x,y);
                    c[j+k+i]=dec(x,y);
                }
            }
        }
        
        if(f==-1) for(int i=0;i<n;i++) c[i]=(ll)c[i]*inv%ha;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n;i++) scanf("%d",a+i);
        for(int i=0;i<=m;i++) scanf("%d",b+i);
        
        m+=n;
        for(n=1,l=0;n<=m;n<<=1) l++;
        for(int i=0;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
        inv=ksm(n,ha-2);
        
        fft(a,1),fft(b,1);
        for(int i=0;i<n;i++) a[i]=(ll)a[i]*b[i]%ha;
        fft(a,-1);
        for(int i=0;i<=m;i++) printf("%d ",a[i]);
        puts("");
        return 0;
    }
  • 相关阅读:
    cmd 中英文 切换
    comparable和comparator
    ORACLE 毫秒转换为日期 日期转换毫秒
    asp.net弹出对话框
    一、DataBinder.Eval的基本格式
    转载 创业
    常用的js验证数字,电话号码,传真,邮箱,手机号码,邮编,日期
    CodeSmith开发系列资料总结
    SQL函数说明大全
    SQLServer游标的使用
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8342958.html
Copyright © 2020-2023  润新知