======多项式exp====== OIWiki上,多项式全家桶里面有多项式exp。 =====exp===== 在多项式exp当中,调用了polyln。 long long exp_t[20005]; void polyexp(long long h[],const int n,long long f[]) { memset(exp_t,0,sizeof(exp_t)); std::fill(f,f+n+n,0); f[0]=1; int t; for(t=2;t<=n;t<<=1) { const int t2=t<<1; polyln(f,t,exp_t); exp_t[0]=(h[0]+1-exp_t[0]+MOD)%MOD; long long i; for(i=1;i!=t;++i) { exp_t[i]=(h[i]-exp_t[i]+MOD)%MOD; } std::fill(exp_t+t,exp_t+t2,0); NTT(f,t2,1); NTT(exp_t,t2,1); for(i=0;i!=t2;++i) { f[i]=f[i]*exp_t[i]%MOD; } NTT(f,t2,-1); std::fill(f+t,f+t2,0); } } =====ln===== 在多项式ln当中,调用了polyinv,derivative和integrate。 long long ln_t[20005]; void polyln(long long h[],const int n,long long f[]) { memset(ln_t,0,sizeof(ln_t)); const int t=n<<1; derivative(h,n,ln_t); std::fill(ln_t+n,ln_t+t,0); polyinv(h,n,f); NTT(ln_t,t,1); NTT(f,t,1); long long i; for(i=0;i!=t;++i) { ln_t[i]=ln_t[i]*f[i]%MOD; } NTT(ln_t,t,-1); integrate(ln_t,n,f); } =====逆===== 多项式求逆什么都不需要调用。 long long inv_t[20005]; void polyinv(long long h[],const int n,long long f[]) { memset(inv_t,0,sizeof(inv_t)); std::fill(f,f+n+n,0); f[0]=QPow(h[0],MOD-2); int t; for(t=2;t<=n;t<<=1) { const int t2=t<<1; std::copy(h,h+t,inv_t); std::fill(inv_t+t,inv_t+t2,0); NTT(f,t2,1); NTT(inv_t,t2,1); long long i; for(i=0;i!=t2;++i) { f[i]=f[i]*((2LL-(f[i]*inv_t[i])%MOD+MOD)%MOD)%MOD; } NTT(f,t2,-1); std::fill(f+t,f+t2,0); } } =====求导和积分===== 在积分中,需要提前把逆元都求出来。这里建议是通过阶乘的方法比较方便。 void derivative(long long h[],const int n,long long f[]) { long long i; for(i=1;i!=n;++i) { f[i-1]=(h[i]*i)%MOD; } f[n-1]=0; } void integrate(long long h[],const int n,long long f[]) { long long i; for(i=n-1;i;--i) { f[i]=(h[i-1]*((FEG[i]*GAM[i-1])%MOD))%MOD; } f[0]=0; } =====NTT===== 使用这个NTT板子,传入长度必须是2的幂,建议为2048。 long long rev[20005]; void NTT(long long A[],long long n,int inv)//数组A,长度n,逆变换(共轭)符号inv { int bit=0; while((1<>1]>>1)|((i&1)<<(bit-1)); if(i =====阶乘初始化===== 其实用这个也可以很方便的大量计算逆元。 long long GAM[20010]; long long FEG[20010]; void init() { GAM[0]=1; long long i; for(i=1;i<20005;i++) { GAM[i]=(GAM[i-1]*i)%MOD; } FEG[20004]=QPow(GAM[20004],MOD-2); for(i=20003;i>=0;i--) { FEG[i]=(FEG[i+1]*(i+1))%MOD; } } =====快速幂===== 是基础。这里的ROOT是原根(生成元),在NTT中用到。 const long long MOD=998244353; const long long ROOT=3; long long QPow(long long bas,long long t) { long long ret=1; for(;t;t>>=1,bas=(bas*bas)%MOD) { if(t&1LL) { ret=(ret*bas)%MOD; } } return ret; } =====例题===== 校赛某道题。比赛结束之后更新。