之前寫過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...