自己码了一个模板...有点辛苦...常数十分大,小心使用
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <algorithm> #include <vector> using namespace std; #define ll long long #define pb push_back ll MOD=; #define SZ 666666 ll w[][SZ]; ll qp(ll a,ll b) { ll ans=; while(b) { ) ans=ans*a%MOD; a=a*a%MOD; b>>=; } return ans; } int K; void fftinit(int n) { ;K<n;K<<=); w[][]=w[][K]=; ll g=qp(,(MOD-)/K); //3是原根 ;i<K;i++) w[][i]=w[][i-]*g%MOD; ;i<=K;i++) w[][i]=w[][K-i]; } void fft(int* x,int v) { ,j=;i<K;i++) { if(i>j) {x[i]^=x[j]; x[j]^=x[i]; x[i]^=x[j];} ;(j^=l)<l;l>>=); } ;i<=K;i<<=) { ;j<K;j+=i) { ;l<i>>;l++) { ll t=(ll)x[j+l+(i>>)]*w[v][K/i*l]%MOD; x[j+l+(i>>)]=(x[j+l]-t+MOD)%MOD; x[j+l]=(x[j+l]+t)%MOD; } } } if(!v) return; ll rv=qp(K,MOD-); ;i<K;i++) x[i]=x[i]*rv%MOD; } struct poly { vector<int> ps; ;} int& operator [] (int x) {return ps[x];} //ps.at(x) );} void dbg() { ; ;i--) { if(!ps[i]) continue; if(fi) { ) printf("+%d",ps[i]); ) printf("+"); ) printf("-"); else printf("+%d",ps[i]); } else { ) printf("%d",ps[i]); ); ) printf("-"); else printf("%d",ps[i]); } ) printf("x^%d",i); ) printf("x"); fi=; } "); putchar(); } void clr() { ; ]) --p; sc(p-); } }; ll gm(ll x) { x=x%MOD; ) x+=MOD; return x; } namespace PolyMul{int ta[SZ],tb[SZ],tc[SZ];} poly operator * (poly a,poly b) { using namespace PolyMul; ||b.cs()<) { poly g; g.sc(a.cs()+b.cs()); ;i<=a.cs();i++) { ;j<=b.cs();j++) g[i+j]=gm(g[i+j]+a[i]*(ll)b[j]%MOD); } return g; } poly c; int t=a.cs()+b.cs(); c.sc(t); fftinit(t+); memset(ta,,sizeof(int)*K); memset(tb,,sizeof(int)*K); memset(tc,,sizeof(int)*K); ;i--) ta[i]=a[i]; ;i--) tb[i]=b[i]; fft(ta,); fft(tb,); ;i<K;i++) tc[i]=(ll)ta[i]*tb[i]%MOD; fft(tc,); ;i--) c[i]=tc[i]; c.clr(); return c; } namespace PolyInv{int ay[SZ],a0[SZ],tmp[SZ];} void ginv(int t) { using namespace PolyInv; ) {a0[]=qp(ay[],MOD-); return;} ginv((t+)>>); fftinit(t+t+); memset(tmp,,sizeof(int)*K); ; ;i<t;i++) tmp[i]=ay[i]; fft(tmp,); fft(a0,); ;i<K;i++) a0[i]=gm((-(ll)tmp[i]*a0[i])%MOD*a0[i]); fft(a0,); ; } poly inv(poly x) { using namespace PolyInv; poly y; y.sc(x.cs()); ;i--) ay[i]=x[i]; ginv(x.cs()+); ;i--) y[i]=a0[i]; y.clr(); return y; } poly operator + (poly a,poly b) { poly w; w.sc(max(a.cs(),b.cs())); ;i--) w[i]=a[i]; ;i--) w[i]+=b[i], w[i]=gm(w[i]); return w; } poly operator - (poly a,poly b) { poly w; w.sc(max(a.cs(),b.cs())); ;i--) w[i]=a[i]; ;i--) w[i]-=b[i], w[i]=gm(w[i]); w.clr(); return w; } void div(poly a,poly b,poly& d,poly& r) { int n=a.cs(),m=b.cs(); ); d[]=; r=a; return;} fftinit(*n); poly aa=a; reverse(aa.ps.begin(),aa.ps.end()); poly bb=b; reverse(bb.ps.begin(),bb.ps.end()); bb.sc(n-m); bb=inv(bb); d=aa*bb; d.sc(n-m); reverse(d.ps.begin(),d.ps.end()); r=a-b*d; r.clr(); } poly operator / (poly a,poly b) { poly d,r; div(a,b,d,r); return d; } poly operator % (poly a,poly b) { poly d,r; div(a,b,d,r); return r; } poly dev(poly x) { ;i<=x.cs();i++) x[i-]=(ll)x[i]*i%MOD; x.sc(x.cs()-); return x; } poly inte(poly x) //C=0 { x.sc(x.cs()+); ;i--) x[i]=x[i-]; x[]=; ;i--) x[i]=(ll)x[i]*qp(i,MOD-)%MOD; return x; } ll qz_(poly& a,ll x) { ll ans=; ;i--) ans=(ans*x%MOD+a[i])%MOD; return gm(ans); } namespace PolyGetv{int xs[SZ],anss[SZ];}; void gv(poly f,int m,int* x,int* ans) { //f.clr(); ) { ;i<=m;i++) ans[i]=qz_(f,x[i]); return; } poly m0,m1,tmp; m0.sc(); m1.sc(); tmp.sc(); m0[]=m1[]=; tmp[]=; ; ;i<=hf;i++) tmp[]=gm(-x[i]), m0=m0*tmp; ;i<=m;i++) tmp[]=gm(-x[i]), m1=m1*tmp; gv(f%m0,hf,x,ans); gv(f%m1,m-hf,x+hf+,ans+hf+); } vector<int> getv(poly a,vector<int> x) { using namespace PolyGetv; a.clr(); if(!x.size()) return vector<int>(); ; ;i<=m;i++) xs[i]=x[i]; gv(a,m,xs,anss); vector<); ;i<=m;i++) ans[i]=anss[i]; return ans; } int main() { }
加减乘逆元除取模求导积分多点求值...感觉够用了。
大部分运算没有用题目测试过...都是小数据/目测啥的...有问题求评论告知。
相关介绍请见picks博客及上一篇FFT入门。
http://picks.logdown.com/posts/177631-fast-fourier-transform
http://picks.logdown.com/posts/189620-inverse-element-of-polynomial