Other polynomial algorithm Portal:
[Polynomial algorithm] (Part 1) FFT Fast Fourier Transform Learning Notes
[Polynomial algorithm] (Part 4) FWT Fast Walsh Transform Learning Notes
[Polynomial algorithm] (Part 5) Divide and Conquer FFT study notes
\(2.Medium-NTT(FNT)\)
definition
NTT\((Number\ Theoretic\ Transforms)\)
(Also known as \ (Fast \ Number The-Theoretic \ the Transform \) , referred \ (FNT \) )
Chinese name: fast number theory transformation
(Not True Transforms)
\ (Q: FFT \) understand, \ (NTT \) what use is it? \ (FFT \) has had enough ah? ?
\ (A: \) wait, with respect to \ (an FFT \) is, \ (NTT \) is more targeted, \ (NTT \) may be calculated in polynomial multiplication modulo sense, so as to avoid \ (an FFT \) a \ (Double \) loss of precision of the case, but \ (NTT \) there are special requirements for the modulus, which will be mentioned below.
So \ (NTT \) is how to achieve it?
In fact, \ (NTT \) implementation method and \ (FFT \) is almost the same, just replace the complex arithmetic modulo operation can be.
Now think about why \ (FFT \) point value represents the unit root to use it?
Because the unit has the following properties for the root \ (an FFT \) utilized to accelerate:
- \(1.\)
\[\omega_n^n=1\]
This is in \ (DFT \) will need time
- \(2.\)
All unit root different from each other, so as to calculate the correct answer (for example, \ (n \) a \ (n \) element equations have a unique solution only linearly independent).
- \(3.\)
\[\begin{cases} \omega_{2n}^{2k}=\omega_n^k(k<\frac n2)\\ \omega_n^{k+\frac n2}=-\omega_n^k(k\ge\frac n2) \end{cases}\]
Obviously this partition in order to proceed
- \(4.\)
\[\sum_{k=0}^{n-1}\omega_n^{k(j-i)}= \begin{cases} 0(i\not=j)\\ n(i=j) \end{cases}\]
This \ (IDFT \) need time.
So then we need to find the right number to meet several properties instead of the above unit root.
Primitive root
With prime \ (P \) , then \ (P \) primitive root \ (G \) satisfies \ (g ^ k \ mod p (1 \ le k <p-1) \) different from each other.
If the prime number then \ (n-P = Q *. 1 + (n-2 = X ^) \) , there is in accordance with Fermat's little theorem \ (a ^ {p-1 } \ equiv 1 (\ mod p) \)
Obviously, \ (G_0 \ equiv. 1-G_ {P} \ equiv. 1 (\ MOD P) \)
Assuming that \ (\ omega_n = G ^ Q \) , can be obtained \ (n-\) non-identical numbers: \ (\ omega_n ^ K (0 \ Le K <n-) \)
2 properties meet
And \ (\ omega_n ^ n \ equiv g ^ {p-1} \ equiv 1 (\ mod p) \)
Meet Property 1
Then you can get:
\(\because p=q*n+1=\frac q2*2n+1,\omega_n=g^q\)
\(\therefore \omega_{2n}=g^{\frac q2}\)
\(\omega_{2n}^{2k}=g^{\frac q2*2k}=g^{qk}=\omega_n^k\)
And
\(\omega_n^{k+\frac n2}\)
\(=\omega_n^k*\omega_n^{\frac n2}\)
\(\because (\omega_n^{\frac n2})^2=\omega_n^n=1\)
\(\therefore \omega_n^{\frac n2}=\pm1\)
\ (\ because \ omega \) different from each other
\(\therefore \omega_n^{\frac n2}=-1\)
\(\therefore \omega_n^{k+\frac n2}=-\omega_n^k\)
3 properties meet
Last: for \ (\ sum_ {k = 0 } ^ {n-1} \ omega_n ^ {k (ji)} \)
If \ (I = J \) , then:
\(\sum_{k=0}^{n-1}\omega_n^{k(j-i)}\)
\(=n*\omega_n^0\)
\(=n\)
If \ (i \ not = J \) , then:
\(\sum_{k=0}^{n-1}\omega_n^{k(j-i)}\)
\ (= \ FRAC {(n-Q-^. 1). 1 a_0-Q {}} \) (geometric series summation, where \ (Q \) as a common ratio \ ((\ omega_n ^ {ji }) \ ) , \ (a_0 \) led by key \ ((\ omega_n ^ 0) \) )
\(\because q^n-1=\omega_n^{n(j-i)}-1=(\omega_n^n)^{j-i}-1=0\)
\(\therefore \sum_{k=0}^{n-1}\omega_n^{k(j-i)}=0\)
In summary, to meet the nature 4
\ (Q: \) what? How primitive root seek?
\(A:\)I know how, Baidu ah
Normally only need to remember \ (998,244,353 \) primitive root is \ (3 \) like \ ((998 244 353 * 119 = 2 ^ {23} + 1) \) , look-up table may be: [Miskcoo apos Space] FFT used in various prime number
Thus, according to the above said, \ (NTT \) framework came out:
The complex operation can be replaced by a modulo.
\ (Q: n \) less than \ (2 ^ {23} \) how to do? Fill up too slow.
\ (A: \) The \ (\ omega_n \) into \ (g ^ {\ frac { p-1} {n}} \) can.
P3803 [template] polynomial multiplication (FFT)
\ (Q: \) Why is \ (FFT \) template?
\(A:\)NTT's not foundBecause the answer to this question does not exceed \ (998 244 353 \) , and then to the modulo will have no effect.
Code:
#include <cstdio>
#include <cctype>
#include <algorithm>
char In[1000005],*p1=In,*p2=In;
#define Getchar (p1==p2&&(p2=(p1=In)+fread(In,1,1000000,stdin),p1==p2)?EOF:*p1++)
inline int Getint()
{
register int x=0,c;
while(!isdigit(c=Getchar));
for(;isdigit(c);c=Getchar)x=x*10+(c^48);
return x;
}
const int p=998244353,g=3;
int Pow(int a,int b)
{
if(b<0)return Pow(Pow(a,p-2),-b);//逆元
int Res=1;
for(;b;b>>=1)
{
if(b&1)Res=Res*1LL*a%p;
a=a*1LL*a%p;
}
return Res%p;
}
int n,m,Maxl;
int a[2100005],b[2100005];
void NTT(int Pol[],int op)//op=1为DFT,-1为IDFT
{
for(int i=0,j=0;i<n;++i)
{
if(i>j)std::swap(Pol[i],Pol[j]);
for(int l=n>>1;(j^=l)<l;l>>=1);
}
for(register int i=2;i<=n;i<<=1)
{
int m=i>>1,Rs=Pow(g,op*(p-1)/i);
for(register int j=0;j<n;j+=i)
{
int Root=1;
for(register int k=0;k<m;++k)
{
int Tmp=Root*1LL*Pol[j+k+m]%p;
Root=Root*1LL*Rs%p;
//int Root=Pow(Omega,op*(p-1)/n*k)
//不预处理单位根,使用秦九韶算法加速
Pol[j+k+m]=Pol[j+k]-Tmp;
Pol[j+k]=Pol[j+k]+Tmp;
Pol[j+k+m]<0?Pol[j+k+m]+=p:0;//减少取模
Pol[j+k]>=p?Pol[j+k]-=p:0;
}
}
}
}
int main()
{
n=Getint(),m=Getint();
for(register int i=0;i<=n;++i)a[i]=Getint();
for(register int i=0;i<=m;++i)b[i]=Getint();
for(Maxl=n+m,n=2;n<=Maxl;n<<=1);
NTT(a,1),NTT(b,1);
for(int i=0;i<n;++i)a[i]=a[i]*1LL*b[i]%p;
NTT(a,-1);
int Invn=Pow(n,p-2);
for(int i=0;i<=Maxl;++i)printf("%d%c",int(a[i]*1LL*Invn%p),i==n-1?'\n':' ');
//答案同样/n
return 0;
}
I believe with \ (FFT \) basis, \ (NTT \) should be very simple.
References :( \ (STO \ Dalao \) )
Fast Fourier Transform from the polynomial multiplication to -Miskcoo
Fourier transform from number theory to transform -Menci