[多项式求逆]JZOJ 3303 城市规划
分析
很裸的求无向连通图个数,求逆瞎搞
#include <iostream> #include <cstdio> #include <cmath> #include <memory.h> using namespace std; const int N=524288; const int P=1004535809; int n,rev[N],j; int fake_a[N],fake_b[N],a[N],b[2][N],C[N],inv[N]; void Get_Rev(int bit,int mxb) {for (int i=1;i<mxb;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<bit-1);} int Pow(int x,int y) {int ans=1;for (;y;y>>=1,x=1ll*x*x%P) ans=1ll*ans*(y&1?x:1)%P;return ans;} void NTT(int *a,int n,int idft) { for (int i=1;i<=n;i++) if (rev[i]>i) swap(a[rev[i]],a[i]); for (int mlen=1;mlen<n;mlen<<=1) { int g1=Pow(3,(P-1)/(mlen<<1)); if (idft<0) g1=Pow(g1,P-2); for (int l=0,len=mlen<<1;l<n;l+=len) { int gk=1; for (int i=l;i<l+mlen;i++) { int x=a[i],y=1ll*a[i+mlen]*gk%P; a[i]=(x+y)%P;a[i+mlen]=(x-y+P)%P; gk=1ll*gk*g1%P; } } } if (idft<0) { int inv=Pow(n,P-2); for (int i=0;i<n;i++) a[i]=1ll*a[i]*inv%P; } } void Roll_Multi(int *a,int *b,int mxb) { for (int i=0;i<mxb;i++) fake_a[i]=0; for (int i=0;i<mxb;i++) fake_b[i]=0; int half=mxb>>1; for (int i=0;i<half;i++) fake_a[i]=a[i],fake_b[i]=b[i]; NTT(fake_a,mxb,1);NTT(fake_b,mxb,1); for (int i=0;i<mxb;i++) fake_a[i]=1ll*fake_a[i]*fake_b[i]%P; NTT(fake_a,mxb,-1); for (int i=0;i<mxb;i++) a[i]=fake_a[i]; } void Calc_Inv() { int bit=1; b[j][0]=Pow(a[0],P-2); for (int mlen=1,len=2;mlen<(n<<1);mlen<<=1,len<<=1,j^=1,++bit) { memset(b[j^1],0,sizeof b[j^1]);Get_Rev(bit,len); for (int i=0;i<mlen;i++) b[j^1][i]=2ll*b[j][i]%P; Roll_Multi(b[j],b[j],len); Roll_Multi(b[j],a,len); for (int i=0;i<mlen;i++) b[j^1][i]=(b[j^1][i]-b[j][i]+P)%P; } } int main() { scanf("%d",&n); inv[0]=1; for (int i=1;i<=n;i++) C[i]=Pow(2,1ll*i*(i-1)/2%(P-1)),inv[i]=1ll*inv[i-1]*Pow(i,P-2)%P; C[0]=C[1]=1; n++; for (int i=0;i<n;i++) a[i]=1ll*C[i]*inv[i]%P; Calc_Inv(); memset(a,0,sizeof a); for (int i=1;i<n;i++) a[i]=1ll*C[i]*inv[i-1]%P; int mxb=1; while (mxb<(n<<1)) mxb<<=1; for (int i=n-1;i<mxb;i++) b[j][i]=0; Roll_Multi(b[j],a,mxb); printf("%lld",1ll*b[j][n-1]*Pow(inv[n-2],P-2)%P); }
在日渐沉没的世界里,我发现了你。