第一问
\qquad
对于第一问,我们只要思考一个点要向外连出一条边的期望次数最后将其乘以
n
n
n 即可. 有两种思路:
\qquad
1.对于期望次数,在第
i
i
i次连到不是自己的概率为
n
−
1
n
i
\frac{n-1}{n^i}
nin−1.那么最后我们所求的就是
a
n
s
(
s
i
n
g
l
e
)
=
∑
i
=
1
+
∞
n
−
1
n
i
∗
i
ans(single)=\sum_{i=1}^{+\infty}\frac{n-1}{n^i}*i
ans(single)=∑i=1+∞nin−1∗i,通过差比数列求和之后可以得出
a
n
s
(
s
i
n
g
l
e
)
→
n
n
−
1
ans(single)\to\frac{n}{n-1}
ans(single)→n−1n,则
a
n
s
=
n
2
n
−
1
ans=\frac{n^2}{n-1}
ans=n−1n2.
\qquad
2.每次选到别的边的概率为
n
−
1
n
\frac{n-1}{n}
nn−1,又因为这是一个几何分布,所以期望就是概率的倒数,也就是
a
n
s
(
s
i
n
g
l
e
)
=
n
n
−
1
ans(single)=\frac{n}{n-1}
ans(single)=n−1n,感性的理解的话就是对于这个模型而言,抽
n
n
n次里面会有
n
−
1
n-1
n−1次符合要求,那么我们平均只需要抽
n
n
−
1
\frac{n}{n-1}
n−1n次,就会有一次符合要求。即
a
n
s
(
s
i
n
g
l
e
)
=
n
n
−
1
ans(single)=\frac{n}{n-1}
ans(single)=n−1n。那么最后的答案就是
a
n
s
=
n
2
n
−
1
ans=\frac{n^2}{n-1}
ans=n−1n2.
第二问
\qquad
对于第二问,由于它是考虑连通块的个数,所以向自己连边的统统不用考虑,简而言之,第二问与第一问无关。
\qquad
这里有一个结论就是在本题条件下,对于每一个确定的图,图的联通块数与其所含环的数量相等。那么我们只需要计算出在所有的图中总共有多少环,再除以图的数量,那么就是最后的答案了。
\qquad
令环的总数为
S
u
m
Sum
Sum,图的总数为
N
u
m
Num
Num.
\qquad
则
N
u
m
=
(
n
−
1
)
n
S
u
m
=
∑
i
=
2
n
∗
C
n
i
∗
(
i
−
1
)
!
∗
(
n
−
1
)
n
−
i
Num=(n-1)^n\\ \qquad\quad Sum=\sum_{i=2}^{n}*C_{n}^{i}*(i-1)!*(n-1)^{n-i}
Num=(n−1)nSum=∑i=2n∗Cni∗(i−1)!∗(n−1)n−i
\qquad
解释一下
S
u
m
Sum
Sum的含义,首先我们先确定环的大小
i
i
i,然后从
n
n
n个点中选择
i
i
i个成环,可以形成环的种类是
(
i
−
1
)
!
(i-1)!
(i−1)!(圆排列),其余点随便连边,最后对其求和(每个确定的环在多少图中出现过)。因为
Σ
\Sigma
Σ所有的图中有多少环是与
Σ
\Sigma
Σ每个确定的环在多少图中出现过的数值是等价的,所以可以进行如上计算。
最后附上AC代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e2+5,p=1e9+7;
inline ll read() {
register ll x=0,f=1;
register char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
ll n,inv[N],fac[N],ct[N];
ll po(ll x, int y) {
register int ans=1;
while(y>0) {
if(y&1)ans=(ans*x)%p;
y>>=1;
x=(x*x)%p;
}
return ans;
}
ll C(int x,int y){
return fac[x]*inv[y]%p*inv[x-y]%p;
}
int main() {
register ll ans=0;
n=read(),ct[0]=inv[1]=inv[0]=fac[0]=fac[1]=1;
ct[1]=n-1;
for(register int i=2;i<=n;i++){
ct[i]=ct[i-1]*(n-1)%p;
fac[i]=fac[i-1]*i%p;
inv[i]=(p-p/i)*inv[p%i];
}
for(register int i=2;i<=n;i++)inv[i]=inv[i-1]*inv[i]%p;
for(register int i=2;i<=n;i++){
ans+=(C(n,i)*fac[i-1]%p*ct[n-i]%p);
ans%=p;
}
ans=(ans*po(ct[n],p-2)%p+p)%p;
printf("%lld\n%lld",n*n%p*po(n-1,p-2)%p,ans);
return 0;
}
//有防作弊操作,请不要复制。