任意模数快速傅立叶变换的两种方法

本文介绍了两种实现任意模数快速傅立叶变换(FFT)的方法:1. 三模数NTT,通过在不同数论模数下进行NTT并应用中国剩余定理合并结果,适用于序列卷积;2. 拆系数FFT(MTT),将系数拆分为两部分再进行还原,需要多次DFT操作。文中还提及了在实际应用中可能遇到的精度问题和运行效率对比。
摘要由CSDN通过智能技术生成

1.三模数NTT

对于初值在 P P P范围内的序列 A ( x ) 和 B ( x ) A(x) 和B(x) A(x)B(x),一次卷积之后大小不超过 n P 2 nP^2 nP2。找三个数论模数分别NTT之后,用中国剩余定理合并。不用大数或者__int128,可以参考下面的做法。
https://blog.csdn.net/u014609452/article/details/68058602

板子题:P4245 【模板】任意模数NTT

code:

// luogu-judger-enable-o2
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int maxn = 2e6 + 10 , g = 3;
const double eps = 1e-3;
int mod;
int rev[maxn];

ll qmul(ll a, ll b, ll c){
   
    a %= c;    b %= c;
    ll ret = a * b - (ll)((long double)a * b / c + eps) * c;
    return ret < 0 ? ret + c : ret;
}

inline ll qpow(ll a,ll b,ll P){
   
    ll ret = 1;
    a %= P;
    for(;b;b>>=1,a=a*a%P) if(b&1) ret = ret * a % P;
    return ret;
}

const int m1 = 998244353,m2 = 1004535809,m3 = 469762049;
const ll _M = (ll)m1 * m2;
const int inv1 = qpow(m1 % m2,m2-2,m2);
const int inv2 = qpow(m2 % m1,m1-2,m1);
const int inv12 = qpow(_M % m3,m3-2,m3);


ll CRT(ll a1, ll a2, ll a3){
   
    ll ret = qmul(a1 * m2 % _M, inv2, _M); 
    (ret += qmul(a2 * m1 % _M, inv1, _M)) %= _M;
    ll ans = ((a3 - ret) % m3 + m3) % m3 * inv12 % m3;
    ans = (ans % mod * (_M % mod) % mod + ret % mod) % mod;
    return ans;
}

struct NTT{
   
    int P;
    int num,w[2][maxn];
    void Pre(int _P,int m){
   
        num = m; P = _P;
        int wn = qpow(g,(P-1)/num,P);
        int _wn = qpow(wn,P-2,P);
        w[1][0] = w[0][0] = 1;
        for(int i = 1;i<num;i++) w[1][i] = (ll)w[1][i-1</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值