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
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</