只会照着板打的蒟蒻。。
多项式求逆,详见:http://blog.miskcoo.com/2015/05/polynomial-inverse
下面是道板题(据说),题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1952
#include<stdio.h> #include<math.h> #include<algorithm> #include<string.h> #include<iostream> #define P 1004535809 #define ll long long #define maxn 400005 using namespace std; ll n,h[maxn],g[maxn],ans[maxn],inv_tmp[maxn],jc[maxn]; ll rev[maxn],dig[maxn],fac[maxn]; ll add(ll a,ll b) { a+=b; return a>=P?a-P:a; } ll sub(ll a,ll b) { a-=b; return a<0?a+P:a; } ll mul(ll a,ll b) { return a*b%P; } ll ksm(ll a,ll b) { ll ans=1; while(b) { if(b&1)ans=(ans*a)%P; a=(a*a)%P; b>>=1; } return ans; } void NTT(ll *p,ll n,ll tt) { ll i,j,k,m; ll t0,t1,aa,bb; for(i=0; i<n; ++i) { for(j=0,k=i,m=n-1;m>0;j=(j<<1)|(k&1),k>>=1,m>>=1); if(i<j)swap(p[i],p[j]);//cout<<rev[i]<<"==========="<<endl; } for(m=1; m<n; m<<=1) { aa=ksm(3,(P-1+tt*(P-1)/(m<<1))%(P-1)); for(i=0; i<n; i+=(m<<1)) { bb=1; for(j=0; j<m; ++j) { t0=p[i+j]; t1=mul(p[i+j+m],bb); //cout<<i+j<<"-"<<t0<<"-"<<i+j+m<<"-"<<t1<<endl; p[i+j]=add(t0,t1); p[i+j+m]=sub(t0,t1); bb=mul(bb,aa); } } } //cout<<" "<<endl; if(tt==-1) { t0=ksm(n,P-2); for(i=0; i<n; ++i) { p[i]=mul(p[i],t0); } } } void poly_inv(ll *a,ll *b,ll n) { if(n==1) { b[0]=ksm(a[0],P-2); return; } poly_inv(a,b,(n+1)>>1); ll N=1; while(N<=n)N<<=1; N<<=1; for (ll i=0; i<=n; ++i) inv_tmp[i]=a[i];//,cout<<a[i]<<"---------"<<endl; for (ll i=n+1; i<N; ++i) inv_tmp[i]=0; NTT(inv_tmp,N,1); NTT(b,N,1); for (ll i=0; i<N; ++i) inv_tmp[i]=b[i]*(2-1*inv_tmp[i]*b[i]%P+P)%P; NTT(inv_tmp,N,-1); for (ll i=0; i<=n; ++i) b[i]=inv_tmp[i]; for (ll i=n+1; i<N; ++i) b[i]=0; } void poly_mul(ll *a,ll *b,ll n) { ll N=1; while(N<=n)N<<=1; N<<=1; for (ll i=n+1; i<N; ++i) a[i]=b[i]=0; NTT(a,N,1); NTT(b,N,1); for (ll i=0; i<N; ++i) a[i]=1ll*a[i]*b[i]%P; NTT(a,N,-1); } int main() { scanf("%lld",&n); h[0]=1; ll k=1,L=0; while(k<=2*n) { k<<=1; L++; } for (ll i=1; i<=n; ++i) h[i]=ksm(2,i*(i-1)/2); jc[0]=1; for(ll i=1; i<=n; ++i)jc[i]=jc[i-1]*i%P; for (ll i=0; i<=n; ++i)fac[i]=ksm(jc[i],P-2); for (ll i=1; i<=n; ++i)g[i]=h[i]*fac[i-1]%P; for (ll i=0; i<=n; ++i)h[i]=h[i]*fac[i]%P; poly_inv(h,ans,n+1); poly_mul(ans,g,n); printf("%lld",(ans[n]*jc[n-1]%P+P)%P); }