P4239 任意模数多项式乘法逆
这个题目简直就是毒瘤,不过还好我们可以使用vector封装要不然真的没法看,现在我们就会用vector封装MTT了,然后有一个代码细节就是这里的求逆还是在模意义下的,所以我们还是需要求逆。
#include<bits/stdc++.h>
#define LL long long
#define FOR(i,a,b) for(register int i=a,end##i=b;i<=end##i;++i)
#define REP(i,a,b) for(register int i=a,end##i=b;i>=end##i;--i)
#define V inline void
#define I inline LL
using namespace std;
I read()
{char x='\0';LL fh=1,sum=0;for(x=getchar();x<'0'||x>'9';x=getchar())if(x=='-')fh=-1;for(;x>='0'&&x<='9';x=getchar())sum=sum*10+x-'0';return fh*sum;
}
#define plx complex<double>
#define poly vector<plx>
const plx im(0,1);
const int N=4e5+9;
const int mod=1e9+7;
const int M=sqrt(mod);
const double pi=acos(-1);
poly a;
int n,rev[N];
plx wn[N];
V print(poly a)
{FOR(i,0,a.size()-1)cout<<a[i]<<' ';cout<<endl;//
}
I ksm(int a,int b)
{int sum=1;while(b){if(b&1)sum=1LL*sum*a%mod;b>>=1;a=1LL*a*a%mod;}return sum;
}
I inv(int x){return ksm(x,mod-2);}
V polypre(int len)
{FOR(i,0,len-1)rev[i]=(rev[i>>1]>>1)|((i&1)*(len>>1));FOR(i,0,len-1)wn[i]=plx(cos(pi/len*i),sin(pi/len*i));
}
V NTT(poly &a,int len,int tp)
{a.resize(len);FOR(i,0,len-1)if(i<rev[i])swap(a[i],a[rev[i]]);for(int mid=1;mid<len;mid<<=1){for(int i=0;i<len;i+=mid<<1){for(int j=0;j<mid;j++){plx x=a[i+j],y=a[i+mid+j]*wn[len/mid*j];a[i+j]=x+y,a[i+mid+j]=x-y;}}}if(tp==-1){FOR(i,0,len-1)a[i]/=len;reverse(&a[1],&a[len]);}
}
V MTT(poly &a,poly &b,int len)
{FOR(i,0,len-1)a[i]=a[i]+b[i]*im;NTT(a,len,1);FOR(i,0,len-1)b[i]=conj(a[i?len-i:0]);FOR(i,0,len-1){plx x=a[i],y=b[i];a[i]=0.5*(x+y);b[i]=0.5*(y-x)*im;}
}
I num(double x){return (x<0)?(LL)(x-0.5)%mod:(LL)(x+0.5)%mod;}
poly operator*(poly a,poly b)
{int n=a.size()+b.size()-1,len=1;while(len<n)len<<=1;poly a0(len),a1(len),b0(len),b1(len);a.resize(len),b.resize(len);FOR(i,0,len-1)a0[i]=(LL)a[i].real()/M,a1[i]=(LL)a[i].real()%M;FOR(i,0,len-1)b0[i]=(LL)b[i].real()/M,b1[i]=(LL)b[i].real()%M;polypre(len);// print(a0),print(a1),print(b0),print(b1);MTT(a0,a1,len),MTT(b0,b1,len);// print(a0),print(a1),print(b0),print(b1);
// cout<<"polymult"<<endl;//FOR(i,0,len-1){a[i]=a0[i]*b0[i]+a1[i]*b0[i]*im;b[i]=a0[i]*b1[i]+a1[i]*b1[i]*im;}NTT(a,len,-1),NTT(b,len,-1);// print(a),print(b);FOR(i,0,len-1){
// cout<<M<<endl;//
// cout<<num(a[i].real())<<' '<<num(a[i].imag())<<' '<<num(b[i].real())<<' '<<num(b[i].imag())<<endl;//a[i]=(1LL*M*M*num(a[i].real())%mod+mod+1LL*M*(num(a[i].imag())+num(b[i].real()))%mod+mod+num(b[i].imag())+mod)%mod;assert(a[i].real()>=0);assert(a[i].real()<mod);
// cout<<a[i]<<endl;//}a.resize(n);
// print(a);return a;
}
poly operator*(int k,poly a)
{
// cout<<"mult"<<endl;//FOR(i,0,a.size()-1)a[i]=k*(LL)a[i].real()%mod;
// cout<<"mult "<<endl;//return a;
}
poly operator+(poly a,poly b)
{if(a.size()<b.size())swap(a,b);FOR(i,0,b.size()-1)a[i]=(LL)(a[i].real()+b[i].real()+mod)%mod,assert(a[i].real()>=0);return a;
}
poly operator-(poly a){FOR(i,0,a.size()-1)a[i]=mod-a[i].real();return a;}
poly operator-(poly a,poly b){return a+(-b);}
poly polyinv(poly a)
{int n=a.size(),len=1;while(len<n*2)len<<=1;poly b={(double)inv((int)a[0].real())},c;
// print(b);a.resize(len);for(int i=2;i<len;i<<=1){c.resize(i);FOR(j,0,i-1)c[j]=a[j];
// cout<<i<<endl;//b=2*b-c*b*b;
// print(b);//b.resize(i);}b.resize(n);return b;
}
int main()
{
// freopen("a.out","w",stdout);n=read();a.resize(n);FOR(i,0,n-1)a[i]=read();
// a=a*a;
// print(a);a=polyinv(a);FOR(i,0,n-1)printf("%d%c",(int)a[i].real(),(i==n-1)?'\n':' ');return 0;
}
/*
5
1 6 3 4 94
1 1 1 1
*/