【BZOJ3456】轩辕朗的城市规划 EGF+多项式求ln
我们构造f(i)和g(i)。
其中f(x)表示由x个节点构成的无向简单连通图的个数。
g(x)表示有x个节点构成的无向简单图(不要求连通)的个数。
显然,由x个节点构成的无向简单图最多能有(x2)条边,那么g(x)=2(x2)。
然后我们构造f(x)和g(x)的EGF:
F(x)=∑∞i=0f(i)×xii!。
G(x)=∑∞i=0g(i)×xii! =∑∞i=02(x2)×xii!。
然后我们又不难发现,G(x)=∑∞i=0F(x)ii!。(这个式子可以这样理解:图中包含1个联通块的生成函数为F(x),包含2个连通块的生成函数为12F2(x),包含3个连通块的生成函数为13!F3(x),以此类推)
考虑到ex的泰勒展开式为∑∞i=0xii!,则 G(x)=eF(x)。
由于多项式G(x)我们已经求得,则F(x)=ln(G(x))。
则答案为[xn]F(n)×n!。
考虑到多项式求ln的时间复杂度为O(n long n),则该算法的时间复杂度为O(n log n)。
1 #include<bits/stdc++.h> 2 #define M (1<<19) 3 #define L long long 4 #define G 3 5 #define MOD 1004535809 6 using namespace std; 7 8 L pow_mod(L x,L k){ 9 L ans=1; 10 while(k){ 11 if(k&1) ans=ans*x%MOD; 12 x=x*x%MOD; k>>=1; 13 } 14 return ans; 15 } 16 17 void change(L a[],int n){ 18 for(int i=0,j=0;i<n-1;i++){ 19 if(i<j) swap(a[i],a[j]); 20 int k=n>>1; 21 while(j>=k) j-=k,k>>=1; 22 j+=k; 23 } 24 } 25 void NTT(L a[],int n,int on){ 26 change(a,n); 27 for(int h=2;h<=n;h<<=1){ 28 L wn=pow_mod(G,(MOD-1)/h); 29 for(int j=0;j<n;j+=h){ 30 L w=1; 31 for(int k=j;k<j+(h>>1);k++){ 32 L u=a[k],t=a[k+(h>>1)]*w%MOD; 33 a[k]=(u+t)%MOD; 34 a[k+(h>>1)]=(u-t+MOD)%MOD; 35 w=w*wn%MOD; 36 } 37 } 38 } 39 if(on==-1){ 40 L inv=pow_mod(n,MOD-2); 41 for(int i=0;i<n;i++) a[i]=a[i]*inv%MOD; 42 reverse(a+1,a+n); 43 } 44 } 45 46 void getinv(L a[],L b[],int n){ 47 if(n==1){b[0]=pow_mod(a[0],MOD-2); return;} 48 static L c[M],d[M]; 49 memset(c,0,M<<3); memset(d,0,M<<3); 50 getinv(a,c,n>>1); 51 for(int i=0;i<n;i++) d[i]=a[i]; 52 NTT(d,n<<1,1); NTT(c,n<<1,1); 53 for(int i=0;i<(n<<1);i++) b[i]=(2*c[i]-d[i]*c[i]%MOD*c[i]%MOD+MOD)%MOD; 54 NTT(b,n<<1,-1); 55 for(int i=0;i<n;i++) b[i+n]=0; 56 } 57 58 void qiudao(L a[],L b[],int n){ 59 for(int i=1;i<n;i++) b[i-1]=a[i]*i%MOD; 60 } 61 void jifen(L a[],L b[],int n){ 62 for(int i=0;i<n;i++) b[i+1]=a[i]*pow_mod(i+1,MOD-2)%MOD; 63 } 64 65 void getln(L a[],L b[],int n){ 66 static L inva[M],pia[M]; 67 memset(inva,0,M<<3); memset(pia,0,M<<3); 68 getinv(a,pia,n); qiudao(a,inva,n); 69 NTT(pia,n<<1,1); NTT(inva,n<<1,1); 70 for(int i=0;i<(n<<1);i++) pia[i]=pia[i]*inva[i]%MOD; 71 NTT(pia,n<<1,-1); 72 jifen(pia,b,n); 73 } 74 75 L a[M]={0},f[M]={0}; 76 L fac[M]={0},invfac[M]={0}; 77 78 int main(){ 79 fac[0]=1; 80 int n; scanf("%d",&n); 81 int nn=1; while(nn<=n) nn<<=1; 82 83 for(int i=1;i<nn;i++) fac[i]=fac[i-1]*i%MOD; 84 invfac[nn-1]=pow_mod(fac[nn-1],MOD-2); 85 for(int i=nn-2;~i;i--) invfac[i]=invfac[i+1]*(i+1)%MOD; 86 87 for(L i=0;i<nn;i++) a[i]=pow_mod(2,i*(i-1)/2)*invfac[i]%MOD; 88 getln(a,f,nn); 89 90 printf("%lld\n",f[n]*fac[n]%MOD); 91 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!