# 洛谷P4245：【模板】MTT （CRT+三模数NTT）

$ans\equiv {c}_{1}\left(\phantom{\rule{1em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}{m}_{1}\right)$

$ans\equiv {c}_{2}\left(\phantom{\rule{1em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}{m}_{2}\right)$

$ans\equiv {c}_{3}\left(\phantom{\rule{1em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}{m}_{3}\right)$

$ans\equiv \left({c}_{1}{m}_{2}Inv\left({m}_{2},{m}_{1}\right)+{c}_{2}{m}_{1}Inv\left({m}_{1},{m}_{2}\right)\right)\left(\phantom{\rule{1em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}{m}_{1}{m}_{2}\right)$

$ans\equiv C\left(\phantom{\rule{1em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}M\right)$

$ans=xM+C=y{m}_{3}+{c}_{3}$

$xM\equiv {c}_{3}-C\left(\phantom{\rule{1em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}{m}_{3}\right)$

$\phantom{\rule{0.667em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}{m}_{3}$$\mod m_3$意义下，$y{m}_{3}$$ym_3$被消掉了。然后有：

$x\equiv \left({c}_{3}-C\right){M}^{-1}\left(\phantom{\rule{1em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}{m}_{3}\right)$

$ans=\left(k{m}_{3}+q\right)M+C=k{m}_{3}M+qM+C$

$ans=k{m}_{1}{m}_{2}{m}_{3}+qM+C$

（其实dalao的blog已经写得很详细了，只不过为了加深记忆我还是再写了一遍QAQ）

CODE：

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<stdio.h>
#include<algorithm>
using namespace std;

const int maxn=1000000;
const long long M[3]={1004535809,998244353,469762049};
const long long g=3;
typedef long long LL;

LL val[3][maxn];

LL A[maxn];
LL B[maxn];

int Rev[maxn];
int N,Lg;

int F[maxn];
int G[maxn];

int n,m;
LL p;

LL Pow(LL x,LL y,LL Mod)
{
if (!y) return 1LL;
LL temp=Pow(x,y>>1,Mod);
temp=temp*temp%Mod;
if (y&1) temp=temp*x%Mod;
return temp;
}

LL Inv0=Pow(M[1]%M[0],M[0]-2LL,M[0]);
LL Inv1=Pow(M[0]%M[1],M[1]-2LL,M[1]);
LL MM=M[0]*M[1];
LL Inv2=Pow(MM%M[2],M[2]-2LL,M[2]);

void DFT(LL *a,int f,LL Mod)
{
for (int i=0; i<N; i++)
if (i<Rev[i]) swap(a[i],a[ Rev[i] ]);

for (int len=2; len<=N; len<<=1)
{
int mid=(len>>1);
LL e=Pow(g,(Mod-1LL)/len,Mod);
if (f==-1) e=Pow(e,Mod-2LL,Mod);

for (LL *p=a; p!=a+N; p+=len)
{
LL wn=1LL;
for (int i=0; i<mid; i++)
{
LL temp=wn*p[mid+i]%Mod;
p[mid+i]=(p[i]-temp+Mod)%Mod;
p[i]=(p[i]+temp)%Mod;
wn=wn*e%Mod;
}
}
}
}

void NTT(int x)
{
for (int i=0; i<N; i++) A[i]=F[i]%M[x],B[i]=G[i]%M[x];
DFT(A,1,M[x]);
DFT(B,1,M[x]);
for (int i=0; i<N; i++) A[i]=A[i]*B[i]%M[x];
DFT(A,-1,M[x]);
LL inv=Pow(N,M[x]-2LL,M[x]);
for (int i=0; i<N; i++) val[x][i]=A[i]*inv%M[x];
}

LL Mul(LL x,LL y,LL Mod)
{
if (!y) return 0LL;
LL temp=Mul(x,y>>1,Mod);
temp=(temp+temp)%Mod;
if (y&1) temp=(temp+x)%Mod;
return temp;
}

LL Get(LL v0,LL v1,LL v2)
{
LL temp1=Mul(v0*M[1]%MM,Inv0,MM);
LL temp2=Mul(v1*M[0]%MM,Inv1,MM);
LL temp=(temp1+temp2)%MM,C=temp;
temp=(v2-temp%M[2]+M[2])%M[2]*Inv2%M[2];
temp=(MM%p*temp%p+C%p)%p;
return temp;
}

int main()
{
freopen("4245.in","r",stdin);
freopen("4245.out","w",stdout);

scanf("%d%d%I64d",&n,&m,&p);
for (int i=0; i<=n; i++) scanf("%d",&F[i]),F[i]%=p;
for (int i=0; i<=m; i++) scanf("%d",&G[i]),G[i]%=p;

N=1,Lg=0;
while (N<n+m+4) N<<=1,Lg++;
for (int i=0; i<N; i++)
for (int j=0; j<Lg; j++)
if (i&(1<<j)) Rev[i]|=(1<<(Lg-j-1));

for (int i=0; i<3; i++) NTT(i);
for (int i=0; i<=n+m; i++) printf("%I64d ", Get(val[0][i],val[1][i],val[2][i]) );
printf("\n");

return 0;
}

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客