luogu P4841 [集训队作业2013]城市规划
题面传送门
这个题我们可以用[清华集训2012]串珠子的思想做掉。
设\(f_i\)为\(i\)个点的无向图数目,\(g_i\)为\(i\)个点的不连通图数目。
枚举最后一个点所在连通块大小可以得到\(g_n=\sum\limits_{i=1}^{n}{C_{i-1}^{n-1}(f_i-g_i)f_{n-i}}\)
拆了可以得到\(\frac{g_n}{(n-1)!}=\sum\limits_{i=1}^{n}{\frac{f_i-g_i}{(i-1)!}\times \frac{f_{n-i}}{(n-i)!}}\)
然后可以得到\(G=(F-G)H\),解得\(G=F-\frac{F}{H+1}\)
因为这个是不连通的,所以答案是\(\frac{F}{H+1}\)
时间复杂度\(O(nlogn)\)
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 3000000
#define K 50
#define mod 1004535809
#define Mod 998244352
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n,m;ll frc[N+5],A[N+5],B[N+5],Inv[N+5],C[N+5];
I ll mpow(ll x,ll y=mod-2){ll Ans=1;while(y) y&1&&(Ans=Ans*x%mod),y>>=1,x=x*x%mod;return Ans;}const ll G=3,invG=mpow(G);
namespace Poly{
int tr[N+5],k;ll C[N+5],D[N+5];I void init(int n){for(k=1;k<=(n<<1);k<<=1);for(RI i=0;i<k;i++) tr[i]=(tr[i>>1]>>1)|((i&1)?k/2:0),C[i]=D[i]=0;}
I void NTT(ll *A,int Fl){
RI i,j,h;re ll now,key,pus;for(i=0;i<k;i++) i<tr[i]&&(swap(A[i],A[tr[i]]),0);
for(i=2;i<=k;i<<=1){
for(key=mpow(Fl?G:invG,(mod-1)/i),j=0;j<k;j+=i)for(now=1,h=j;h<j+i/2;h++) pus=A[h+i/2]*now%mod,A[h+i/2]=(A[h]+mod-pus)%mod,A[h]=(A[h]+pus)%mod,now=now*key%mod;
}if(Fl) return;ll Invn=mpow(k);for(i=0;i<k;i++) A[i]=A[i]*Invn%mod;
}
namespace Inv{
I void Sl(ll *A,ll *B,int n){
if(n==1){B[0]=mpow(A[0]);return;}Sl(A,B,n+1>>1);init(n);RI i;for(i=0;i<n;i++) C[i]=A[i],D[i]=B[i];NTT(C,1);NTT(D,1);for(i=0;i<k;i++) C[i]=(2-C[i]*D[i]%mod+mod)*D[i]%mod;NTT(C,0);for(i=0;i<n;i++) B[i]=C[i];
}
}
}
int main(){
freopen("1.in","r",stdin);
RI i;scanf("%d",&n);for(Inv[0]=frc[0]=i=1;i<=n;i++) frc[i]=frc[i-1]*i%mod,Inv[i]=mpow(frc[i]);for(i=1;i<=n;i++) B[i]=mpow(2,1ll*i*(i-1)/2)*Inv[i]%mod,A[i]=B[i]*i%mod;
B[0]++;Poly::Inv::Sl(B,C,n+1);memcpy(B,A,sizeof(B));Poly::init(n+1);Poly::NTT(B,1);Poly::NTT(C,1);for(i=0;i<Poly::k;i++) B[i]=B[i]*C[i]%mod;Poly::NTT(B,0);printf("%lld\n",B[n]*frc[n-1]%mod);
}

浙公网安备 33010602011771号