P4239 任意模数多项式乘法逆(多项式/ MTT)
生活随笔
收集整理的這篇文章主要介紹了
P4239 任意模数多项式乘法逆(多项式/ MTT)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
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 */ 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的P4239 任意模数多项式乘法逆(多项式/ MTT)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CF623E Transforming
- 下一篇: 减肥是先消耗脂肪还是肌肉