任意模數ntt 模板篇 NTT和三模數NTT

2021-10-25 17:14:37 字數 2192 閱讀 3301

之前寫過fft的筆記. 我們知道fft是在複數域上進行的變換.

而且經過數學家的證明, dft是複數域上唯一滿足迴圈卷積性質的變換.

而我們在oi中, 經常遇到對***x取模的題目, 這就啟發我們可不可以在模運算的意義下找乙個這樣的變換.

然後我們發現有個神奇的東西, 原根\(g\), 這東西在模意義下相當於單位復根\(-e^}\).

所以我們預處理一下\(g\)的冪和逆元, 然後改一下fft的**就出現了快速數論變換ntt

懶得寫了 直接上**:

void getwn()=10^級別.

所以我們可以找三個乘積\(>10^\)的ntt-friendly的數, 然後分別ntt再想辦法合併.

我們假如答案是ans, 那我們做三次ntt後就能得到如下三個柿子.

\left\

ans\equiv a_1(\mod m_1)\\

ans\equiv a_2(\mod m_2)\\

ans\equiv a_3(\mod m_3)

\end\right.

我們把前兩個柿子通過中國剩餘定理合併, 就可以得到

\left\

ans\equiv a(\mod m)\\

ans\equiv a_3(\mod m_3)

\end\right.

其中, \(m=m_1*m_2\)

這樣我們設\(ans=km+a\),

km+a\equiv a_3(\mod m_3) \k=(a_3-a)*m^ (\mod m_3)

這樣我們求出\(k\)然後代回到\(ans=km+a\)就可以求對任意模數取模的結果了.

中國剩餘定理合併的時候直接乘是可以爆long long的, 所以我們要用到\(o(1)\)快速乘~

下面上一波**: luogu4245 【模板】mtt

哎呀覺得自己碼風有點醜啊qwq

#include

#include

#include

typedef long long ll;

const int n=600020,p0=469762049,p1=998244353,p2=1004535809;

const ll m=1ll*p0*p1;

int wn[20],nw[20],rev[n],n,lg,p;

int qpow(int a,int b,int p,int s=1) int x=qpow(n,p-2,p);

if(!f) for(int i=0;i

char c1[n],c2[n]; int a[n],b[n],c[n],d[n],ans[3][n];

int main(){

int l1,l2; scanf("%d%d%d",&l1,&l2,&p);

for(int i=0;i<=l1;++i) scanf("%d",&a[i]),a[i]%=p;

for(int i=0;i<=l2;++i) scanf("%d",&b[i]),b[i]%=p;

for(n=1;n

std::copy(a,a+n,c); std::copy(b,b+n,d);

ntt(c,1,p0); ntt(d,1,p0);

for(int i=0;i

std::copy(a,a+n,c); std::copy(b,b+n,d);

ntt(c,1,p1); ntt(d,1,p1);

for(int i=0;i

std::copy(a,a+n,c); std::copy(b,b+n,d);

ntt(c,1,p2); ntt(d,1,p2);

for(int i=0;i

ntt(ans[0],0,p0); ntt(ans[1],0,p1); ntt(ans[2],0,p2);

for(int i=0;i

ll a=mul(1ll*ans[0][i]*p1%m,qpow(p1%p0,p0-2,p0),m)

+mul(1ll*ans[1][i]*p0%m,qpow(p0%p1,p1-2,p1),m);

if(a>m) a-=m;

ll k=((ans[2][i]-a)%p2+p2)%p2*qpow(m%p2,p2-2,p2)%p2;

a[i]=1ll*(k%p)*(m%p)%p+a%p;

if(a[i]>p) a[i]-=p;

for(int i=0;i<=l1+l2;++i) printf("%d",a[i]);

原文:

任意模數ntt 任意模數NTT

任意模數 ntt 眾所周知,為了滿足單位根的性質,ntt 需要質數模數,而且需要能寫成 a2 1 且 2 k ge n 比較常用的有 998244353,1004535809,469762049 這三個原根都是 3 如果要任意模數怎麼辦?n 次多項式在模 m 下乘積,最終係數一定不會大於 nm 2 ...

任意模數NTT學習筆記

這兩天有點頹,所以東西學的也很慢。這個一眼就能推出來的活生生卡了我兩天。說幾個細節 柿子 m 通常設定為 32768 把上一步的幾個韓束化成 a,b,c,d 的形式,答案就是 一看卷積,多搞幾次 fft 就過去了。陣列記得開大。n 2 左右。include using namespace std d...

任意模數NTT 拆係數FFT

給定 2 個多項式 f x g x 請求出 f x g x 係數對 p 取模,且不保證 p 可以分解成 p a cdot 2 k 1 之形式。不關心 1 leq n leq 10 5,0 leq a i,b i leq 10 9,2 leq p leq 10 9 9 現在這裡有兩個多項式 a x b...