什么鬼题目名字???
好吧解释一下,考试题,题目a、b、c。。。往常套路了。
题目要求的就是有 n n n 个点,你需要连 n + 1 n+1 n+1 条边,使得原来的图是联通图,而且在删除任意一条边时不会使图不连通,问你方案数。
那么很显然有两种情况(也不算很显然吧,反正你推样例的时候会推出来)。
第一种:先把这 n n n 个点连成一个环,再在环上连一条对角线,公式为 ( n ∗ ( n − 1 ) / 2 − 3 ) ∗ ( n ! / 12 ) (n*(n-1)/2-3)*(n!/12) (n∗(n−1)/2−3)∗(n!/12)。 ( n ∗ ( n − 1 ) / 2 − 3 ) (n*(n-1)/2-3) (n∗(n−1)/2−3) 表示 n n n 个点能构成的不同的环的个数, ( n ! / 12 ) (n!/12) (n!/12) 是构成的环的对角线条数,相乘即可。
第二种:8字形,即有一个公共点的双环,公式为 ( n − 4 ) ∗ ( n ! / 8 ) (n-4)*(n!/8) (n−4)∗(n!/8)。我们可以先确定环的大小,某一个环的大小可以从 3 3 3 到 n − 2 n-2 n−2,然后另一个环的大小也就确定了,所以是 n − 4 n-4 n−4 种, n ! n! n! 是枚举全排列,算上两环交换重复 ∗ 2 *2 ∗2, 某一个环逆序 ∗ 2 *2 ∗2,有两个环那就 ∗ 4 *4 ∗4,所以相同的一种情况被重复了 8 8 8 次,所以要除以 8 8 8。
所以总的公式就是 f [ n ] = ( n − 4 ) ∗ ( n ! / 8 ) + ( n ∗ ( n − 1 ) / 2 − 3 ) ∗ ( n ! / 12 ) f[n]=(n-4)*(n!/8)+(n*(n-1)/2-3)*(n!/12) f[n]=(n−4)∗(n!/8)+(n∗(n−1)/2−3)∗(n!/12),这里要注意因为要mod,所以处理的时候要逆元或者再开数组存除以 8 8 8 和 12 12 12 阶乘。
然后你就有80分了。
(听说100分就是提前打表出来3e5、6e5、9e5的阶乘再写。。。)
80分的code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10,MOD=1e9+7;
long long f[N],g[N],h[N],n;
void freo(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
}
void init(){
scanf("%lld",&n);
}
void work(){
f[4]=1*2*3*4;
g[4]=f[4]/8;
h[4]=f[4]/12;
for(int i=4;++i<N;f[i]=f[i-1]*i%MOD,g[i]=g[i-1]*i%MOD,h[i]=h[i-1]*i%MOD);
}
void prin(){
printf("%lld",((n-4)*g[n]%MOD+((n*(n-1)/2%MOD-3+MOD)%MOD)*h[n]%MOD)%MOD);
}
int main(){
freo();
init();
work();
prin();
return 0;
}