zoukankan      html  css  js  c++  java
  • 快速数论变换ntt

    // luogu-judger-enable-o2·
    /*(
     ntt 模板
     luogu P3803
    in:
     n , m
     0,...,a[n]
     0,...,b[m]
    
    example:
     1 2
     1 2
     1 2 1
     1 4 5 2
    */
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define int long long
    void in(int &x){
        x=0;char c=getchar();
        long long y=1;
        while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        x*=y;
    }
    void o(int x){
        if(x<0){x=-x;putchar('-');}
        if(x>9)o(x/10);
        putchar(x%10+'0');
    }
    
    const int _ = 1e7+10;
    const int mod = 998244353;//模数
    const int G = 3;//原根
    int ppo(int x,int p){
        int t=x,res=1;
        while(p>0){
            if(p&1)res=(res*t)%mod;
            t=(t*t)%mod;
            p>>=1;
        }
        return res%mod;
    }
    int n,m;
    int limit = 1 , bit;
    int a[_],b[_];
    int r[_];
    void ntt(int *A,int type)
    {
        for(int i=0;i<limit;i++)if(i<r[i])swap(A[i],A[r[i]]);
        for(int mid = 1;mid < limit;mid<<=1){//当前区间的一半
            int wn  = ppo(type==1 ? G:ppo(G,mod-2),(mod-1)*ppo(mid<<1,mod-2)%mod);
            for(int R = mid << 1,j = 0;j < limit;j+=R){//回溯区间大小 最大不超过 limit
                int w = 1;
                for(int k = 0 ;k<mid;k++,w=w*wn%mod){
                    int x = A[j+k],y = w*A[j+mid+k]%mod;
                    A[j+k]=x+y,A[j+k]%=mod;
                    A[j+k+mid]=x-y+mod,A[j+k+mid]%=mod;
                }
            }
    
        }
    }
    signed main() {
        in(n);in(m);
        for(int i = 0;i <= n;i++)cin>>(a[i]),a[i]=(a[i]+mod)%mod;
        for(int j = 0;j <= m;j++)cin>>(b[j]),b[j]=(b[j]+mod)%mod;
        while (limit<=n+m)limit<<=1,bit++;
        for(int i = 0 ;i<limit;i++){
            r[i]=(r[i>>1]>>1)|((i&1)<<(bit-1));//反转序列
        }
        ntt(a,1);
        ntt(b,1);
        for(int i=0;i<=limit;i++)a[i]=a[i]*b[i]%mod;//y;
        ntt(a,-1);
        int inv = ppo(limit,mod-2);//n 的逆元  除n运算
        for(int i=0;i<=n+m;i++){
            printf("%lld ",a[i]*inv%mod);
        }
        return 0;
    }
    
  • 相关阅读:
    禁止在工作流设计器启动持续活动的重新编译
    设计流程 工作流
    workflow 工作流
    访问调度控制 时间控件
    如何:实现一个视图项目
    Python多线程之threading.Thread实现
    gcc 编译流程分析
    如何编写Makefile?
    linux 文件夹的颜色代表什么意思
    STL容器的迭代器失效的原因
  • 原文地址:https://www.cnblogs.com/yesuweiYYYY/p/15048807.html
Copyright © 2011-2022 走看看