2 条题解
-
0
#include <bits/stdc++.h> #pragma GCC optimize(2,3,"Ofast") using namespace std; typedef long long ll; const int N=55; const int P=1e9+7; int n,m; template<typename T>T qpow(T a,ll b){ T res=1; for(;b;b>>=1,a*=a) if(b&1)res*=a; return res; } class mint{ public: ll val; mint(ll _val=0){val=(_val%P+P)%P;} mint operator + (const mint& _){return (val+_.val)%P;} mint operator +=(const mint& _){return *this=*this+_;} mint operator - (const mint& _){return (val-_.val+P)%P;} mint operator -=(const mint& _){return *this=*this-_;} mint operator * (const mint& _){return val*_.val%P;} mint operator *=(const mint& _){return *this=*this*_;} mint operator / (const mint& _){return *this*qpow(_,P-2);} mint operator /=(const mint& _){return *this=*this/_;} mint operator ^ (const ll & _){return qpow(*this,_);} mint operator ^=(const ll & _){return *this=*this^_;} }; mint F[N][N],G[N][N][N],H[N]; mint pow2[N*N],C[N][N]; void init(int N){ for(int i=0;i<=N;i++){ C[i][0]=C[i][i]=1; for(int j=1;j<i;j++) C[i][j]=C[i-1][j-1]+C[i-1][j]; } pow2[0]=1; for(int i=1;i<=N*N;i++)pow2[i]=pow2[i-1]*2; } int main(){ scanf("%d%d",&n,&m); init(n); G[0][0][0]=1; for(int i=1;i<=n;i++){ H[i]=pow2[i*(i-1)/2]; for(int j=1;j<i;j++) H[i]-=C[i-1][j-1]*H[j]*pow2[(i-j)*(i-j-1)/2]; F[i][0]=H[i]; for(int j=1;j<i;j++){ for(int k=1;k<i;k++){ mint temp=C[i-1][k-1]*F[k][0]; mint kx=k; for(int x=1;x<=min(i-k,j);x++,kx*=k) F[i][j]+=temp*G[i-k][j-x][x]*kx; } F[i][0]-=F[i][j]; } for(int j=0;j<i;j++) for(int k=1;k<=i;k++) for(int p=1;p<=i;p++){ mint temp=C[i-1][p-1]*p; for(int q=0;q<=j;q++) G[i][j][k]+=temp*F[p][q]*G[i-p][j-q][k-1]; } } mint ans; for(int i=0;i<=min(m,n-1);i++)ans+=F[n][i]; printf("%lld\n",ans.val); }定义
- 以下定义中图均为有标号无向连通图
- F[i,j] = i 个结点 j 条割边方案数
- G[i,j,k] = i 个结点,j 条割边,k 个连通块的方案数
- H[i] = i 个结点方案数
状态转移方程
- F[i,j] = \sum_{k=1}^{i-1} C(i-1,k-1) \cdot F[k,0] \cdot \sum_{x=1}^{\min(i-k,j)} G[i-k,j-x,x] \cdot k^x
- F[i,0] = H[i] - \sum_{j=1}^{i-1} F[i,j]
- G[i,j,k] = \sum_{p=1}^{i} \sum_{q=0}^{k} F[p,q] \cdot C(i-1,p-1) \cdot p \cdot G[i-p,j-q,k-1]
- H[i] = 2^{i(i-1)/2} - \sum_{j=1}^{i-1} C(i-1,j-1) \cdot H[j] \cdot 2^{(i-j)(i-j-1)/2}
-
0
#include<bits/stdc++.h> #pragma GCC optimize(2,3,"Ofast") using namespace std; typedef long long ll; const int N=55; const int P=1e9+7; int n,m; template<typename T>T qpow(T a,ll b){ T res=1; for(;b;b>>=1,a*=a) if(b&1)res*=a; return res; } class mint{ public: ll val; mint(ll _val=0){val=(_val%P+P)%P;} mint operator + (const mint& _){return (val+_.val)%P;} mint operator +=(const mint& _){return *this=*this+_;} mint operator - (const mint& _){return (val-_.val+P)%P;} mint operator -=(const mint& _){return *this=*this-_;} mint operator * (const mint& _){return val*_.val%P;} mint operator *=(const mint& _){return *this=*this*_;} mint operator / (const mint& _){return *this*qpow(_,P-2);} mint operator /=(const mint& _){return *this=*this/_;} mint operator ^ (const ll & _){return qpow(*this,_);} mint operator ^=(const ll & _){return *this=*this^_;} }; mint F[N][N],G[N][N][N],H[N]; mint pow2[N*N],C[N][N]; void init(int N){ for(int i=0;i<=N;i++){ C[i][0]=C[i][i]=1; for(int j=1;j<i;j++) C[i][j]=C[i-1][j-1]+C[i-1][j]; } pow2[0]=1; for(int i=1;i<=N*N;i++)pow2[i]=pow2[i-1]*2; } int main(){ scanf("%d%d",&n,&m); init(n); G[0][0][0]=1; for(int i=1;i<=n;i++){ H[i]=pow2[i*(i-1)/2]; for(int j=1;j<i;j++) H[i]-=C[i-1][j-1]*H[j]*pow2[(i-j)*(i-j-1)/2]; F[i][0]=H[i]; for(int j=1;j<i;j++){ for(int k=1;k<i;k++){ mint temp=C[i-1][k-1]*F[k][0]; mint kx=k; for(int x=1;x<=min(i-k,j);x++,kx*=k) F[i][j]+=temp*G[i-k][j-x][x]*kx; } F[i][0]-=F[i][j]; } for(int j=0;j<i;j++) for(int k=1;k<=i;k++) for(int p=1;p<=i;p++){ mint temp=C[i-1][p-1]*p; for(int q=0;q<=j;q++) G[i][j][k]+=temp*F[p][q]*G[i-p][j-q][k-1]; } } mint ans; for(int i=0;i<=min(m,n-1);i++)ans+=F[n][i]; printf("%lld\n",ans.val); } /* ======================= > 定义 - 以下定义中图均为有标号无向连通图 - F[i,j]= i 个结点 j 条割边方案数 - G[i,j,k]= i 个结点,j 条割边,k 个连通块的方案数 - H[i]= i 个结点方案数 ======================= > 状态转移方程 - F[i,j] = sum{k,1,i-1} C(i-1,k-1) * F[k,0] * sum{x,1,min(i-k,j)} G[i-k,j-x,x] * k^x - F[i,0] = H[i] - sum{j,1,i-1} F[i,j] - G[i,j,k] = sum{p,1,i} sum{q,0,k} F[p,q] * C(i-1,p-1) * p * G[i-p,j-q,k-1] - H[i]= 2^(i(i-1)/2) - sum{j,1,i-1} C(i-1,j-1) * H[j] * 2^((i-j)(i-j-1)/2) ======================= */
- 1
信息
- ID
- 1505
- 时间
- 800ms
- 内存
- 64MiB
- 难度
- 8
- 标签
- 递交数
- 13
- 已通过
- 7
- 上传者