P4841,jzoj3303-城市规划【NTT,多项式求逆,dp】
正題
題目鏈接:https://www.luogu.org/problemnew/show/P4841
題目大意
求nnn個點的簡單聯通無向圖的個數。
解題思路
首先考慮n2n^2n2,我們設gig_igi?表示iii個點的簡單無向圖的個數,顯然gi=2n(n?1)2g_i=2^{\frac{n(n-1)}{2}}gi?=22n(n?1)?
然后我們設fif_ifi?表示iii個點的簡單無向聯通圖的個數,然后我們只要固定一個聯通塊大小為k(k<i)k(k<i)k(k<i)然后剩下的點都不與其聯通就可以去掉不連通的。
也就是fn=gn?∑i=1n?1fi?Cn?1i?1?gn?if_n=g_n-\sum_{i=1}^{n-1}f_i*C_{n-1}^{i-1}*g_{n-i}fn?=gn??i=1∑n?1?fi??Cn?1i?1??gn?i?
這就是O(n2)O(n^2)O(n2)
之后我們考慮優化,將CCC拆開
fn=gn?∑i=1n?1fi?(i?1)!(n?i)!(i?1)!?gn?if_n=g_n-\sum_{i=1}^{n-1}f_i*\frac{(i-1)!}{(n-i)!(i-1)!}*g_{n-i}fn?=gn??i=1∑n?1?fi??(n?i)!(i?1)!(i?1)!??gn?i?
然后將nnn的項提出
fn=gn?∑i=1n?1fi?(n?1)!(n?i)!(i?1)!?gn?if_n=g_n-\sum_{i=1}^{n-1}f_i*\frac{(n-1)!}{(n-i)!(i-1)!}*g_{n-i}fn?=gn??i=1∑n?1?fi??(n?i)!(i?1)!(n?1)!??gn?i?
gn(n?1)!=∑i=1nfi(i?1)!gn?i(n?i)!\frac{g_n}{(n-1)!}=\sum_{i=1}^n\frac{f_i}{(i-1)!}\frac{g_{n-i}}{(n-i)!}(n?1)!gn??=i=1∑n?(i?1)!fi??(n?i)!gn?i??
然后使用NTTNTTNTT卷起來
F(x)=∑i=1+∞fi(i?1)!xiF(x)=\sum_{i=1}^{+\infty}\frac{f_i}{(i-1)!}x^iF(x)=i=1∑+∞?(i?1)!fi??xi
G(x)=∑i=0+∞gn?i(n?i)!xiG(x)=\sum_{i=0}^{+\infty}\frac{g_{n-i}}{(n-i)!}x^iG(x)=i=0∑+∞?(n?i)!gn?i??xi
H(x)=∑n=1+∞gn(n?1)!xnH(x)=\sum_{n=1}^{+\infty}\frac{g_n}{(n-1)!}x^nH(x)=n=1∑+∞?(n?1)!gn??xn
上兩個的iii與最后一個的nnn同理,所以現在有
H(x)=F(x)G(x)H(x)=F(x)G(x)H(x)=F(x)G(x)
F(x)=H(x)G(x)?1F(x)=H(x)G(x)^{-1}F(x)=H(x)G(x)?1
現在我們要求F(x)F(x)F(x)而H(x)H(x)H(x)和G(x)G(x)G(x)都知道。
那么我們將G(x)G(x)G(x)進行求逆后用NTTNTTNTT與H(x)H(x)H(x)相乘就好了。
codecodecode
#include<cstdio> #include<algorithm> #include<cstring> #define ll long long using namespace std; const ll N=131000,XJQ=1004535809; ll n,fac[N],inv[N],r[N*4],Gi; ll power(ll x,ll b) {ll ans=1;while(b){if(b&1) ans=ans*x%XJQ;x=x*x%XJQ;b>>=1;}return ans; } struct Poly{ll x[N*4];void cpy(Poly &a,ll len){for(ll i=0;i<len;i++)x[i]=a.x[i];}void reset(ll len){for(ll i=0;i<len;i++)x[i]=0;}void ntt(ll n,ll op){for(ll i=1;i<n;i++)r[i]=(r[i>>1]>>1)|((i&1)?n>>1:0);for(ll i=0;i<n;i++)if(i<r[i])swap(x[i],x[r[i]]);for(ll p=2;p<=n;p<<=1){ll len=p>>1,tmp=power(3,(XJQ-1)/p);if(op==-1)tmp=power(tmp,XJQ-2);for(ll k=0;k<n;k+=p){ll buf=1;for(ll i=k;i<k+len;i++){ll tt=buf*x[len+i]%XJQ;x[len+i]=(x[i]-tt+XJQ)%XJQ;x[i]=(x[i]+tt)%XJQ;buf=buf*tmp%XJQ;}}}} }; Poly get_inv(Poly &a,Poly &b,Poly &c,ll n){if(a.x[0]==1) b.x[0]=1;else b.x[0]=power(a.x[0],XJQ-2);for(ll w=1;(1<<(w-1))<n;++w){ll len=(1<<w);c.cpy(a,len);c.ntt(len*2,1);b.ntt(len*2,1);for(ll i=0;i<(len<<1);i++)b.x[i]=(2-b.x[i]*c.x[i]%XJQ+XJQ)*b.x[i]%XJQ;b.ntt(len*2,-1);ll inv=power(len*2,XJQ-2);for(ll i=0;i<len;i++)b.x[i]=b.x[i]*inv%XJQ;for(ll i=len;i<len*2;i++) b.x[i]=0;}return b; } Poly H,Ginv,a,b; int main() {scanf("%lld",&n);n++;fac[0]=fac[1]=inv[0]=inv[1]=1;for(ll i=2;i<=n;i++){inv[i]=XJQ-(XJQ/i)*inv[XJQ%i]%XJQ;fac[i]=fac[i-1]*inv[i]%XJQ;}Ginv.x[0]=1;for(ll i=1;i<n;i++){ll tmp=power(2,i*(i-1)/2%(XJQ-1));H.x[i]=tmp*fac[i-1]%XJQ,Ginv.x[i]=tmp*fac[i]%XJQ;}Ginv=get_inv(Ginv,a,b,n);ll len=1,w=0;while(len<(n<<1)) len<<=1,w++;for(ll i=n;i<len;i++) Ginv.x[i]=0;H.ntt(len,1);Ginv.ntt(len,1);for(ll i=0;i<=len;i++)H.x[i]=H.x[i]*Ginv.x[i]%XJQ;H.ntt(len,-1);printf("%lld",power(inv[2],w)*H.x[n-1]%XJQ*power(fac[n-2],XJQ-2)%XJQ); }總結
以上是生活随笔為你收集整理的P4841,jzoj3303-城市规划【NTT,多项式求逆,dp】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 发现电脑启动不正常电脑启动显示电脑遇到问
- 下一篇: 欢乐纪中某A组赛【2019.7.5】