c's 80分

什么鬼题目名字???

好吧解释一下,考试题,题目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(n1)/23)(n!/12) ( n ∗ ( n − 1 ) / 2 − 3 ) (n*(n-1)/2-3) (n(n1)/23) 表示 n n n 个点能构成的不同的环的个数, ( n ! / 12 ) (n!/12) (n!/12) 是构成的环的对角线条数,相乘即可。

第二种:8字形,即有一个公共点的双环,公式为 ( n − 4 ) ∗ ( n ! / 8 ) (n-4)*(n!/8) (n4)(n!/8)。我们可以先确定环的大小,某一个环的大小可以从 3 3 3 n − 2 n-2 n2,然后另一个环的大小也就确定了,所以是 n − 4 n-4 n4 种, 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]=(n4)(n!/8)+(n(n1)/23)(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;
}
100分的话貌似只能写逆元了,害。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值