题解:P12992 [GCJ 2022 #1C] Intranets
简化题意
暴搜即可。
:::info[code]
//by lovely Autumn_Rain
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define For(i,l,r) for(int i=l;i<=r;i++)
int n,m,P;
vector<int>deg;
ll ans=0;
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1)res=res*a%P;
a=a*a%P;b>>=1;
}
return res;
}
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
void dfs(int cnt,vector<int>°,ll res){
bool f=0;
For(i,1,n)if(deg[i]==0){f=1;break;}
if(!f){
if(cnt==m)ans=(ans+res)%P;
return;
}
vector<pii>G;
ll num=0;
For(u,1,n-1){
For(v,u+1,n){
if(!deg[u]||!deg[v]){
G.pb(mp(u,v));
num++;
}
}
}
if(num==0)return;
ll inv=qpow(num,P-2)%P;
for(pii &x:G){
int u=x.fi,v=x.se;
deg[u]++;deg[v]++;
dfs(cnt+1,deg,res*inv%P);
deg[u]--;deg[v]--;
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m>>P;
deg.resize(n+1,0);
dfs(0,deg,1);
cout<<ans%P;
return 0;
}
:::
n\le 4\times 10^3
考虑
:::info[code]
//by lovely Autumn_Rain
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define For(i,l,r) for(int i=l;i<=r;i++)
int n,m;
ll P;
const int N=4e3+10;
ll f[N][N];
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1)res=res*a%P;
a=a*a%P;
b>>=1;
}
return res;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m>>P;
f[0][n]=1;
For(i,0,m-1){
for(int j=n;j>=1;j--){
if(f[i][j]==0)continue;
ll t=(n*(n-1)/2-(n-j)*(n-j-1)/2+P)%P;
ll inv=qpow(t,P-2)%P;
if(j>=2)f[i+1][j-2]=(f[i+1][j-2]+j*(j-1)/2*inv%P*f[i][j]%P+P)%P;
if(j>=1)f[i+1][j-1]=(f[i+1][j-1]+j*(n-j)*inv%P*f[i][j]%P+P)%P;
}
}
cout<<(f[m][0]+P)%P;
return 0;
}
:::
m=n-1
打表或者推式子,答案为
:::info[code]
//by lovely Autumn_Rain
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define For(i,l,r) for(int i=l;i<=r;i++)
int n,m;
ll P;
const int N=4e3+10;
ll f[N][N];
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1)res=res*a%P;
a=a*a%P;
b>>=1;
}
return res;
}
ll cal(int x){
ll inv=qpow(x+1,P-2)%P;
ll res=1;
For(i,x+1,2*x){
res=res*i%P;
int ar=i-x;
ll t=qpow(ar,P-2)%P;
res=res*t%P;
}
return res*inv%P;
}
void solve(){
ll res=cal(n-1);
ll inv=qpow(res,P-2)%P;
cout<<qpow(2,n-2)*inv%P;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m>>P;
if(m==n-1){solve();return 0;}
f[0][n]=1;
For(i,0,m-1){
for(int j=n;j>=1;j--){
if(f[i][j]==0)continue;
ll t=(n*(n-1)/2-(n-j)*(n-j-1)/2+P)%P;
ll inv=qpow(t,P-2)%P;
if(j>=2)f[i+1][j-2]=(f[i+1][j-2]+j*(j-1)/2*inv%P*f[i][j]%P+P)%P;
if(j>=1)f[i+1][j-1]=(f[i+1][j-1]+j*(n-j)*inv%P*f[i][j]%P+P)%P;
}
}
cout<<(f[m][0]+P)%P;
return 0;
}
:::
O(n) 正解
两种操作情况。
- 一个孤立点和一个非孤立点操作。
- 两个孤立点连边。
假设做了