Codeforces Round #663 (Div. 2) C. Cyclic Permutations(思维)

题目链接:传送门

思路:可以先算无环的情况数,再用全部情况数减,算无环情况的关键点有两个:
1)除了最大数n以外,每个数一定至少有一条边指向另一个数,当每个数只有一条边连出去时(共n-1条边),图是无环的,即只要有一个数连两条边出去就有环。
2)对于特定的数i (i <= n - 1 ),要保证无环,从i = 1开始处理,i = 1时,若只连出一条边,必须保证比1大的所有数都在左边,或比1大的所有数都在右边,位置关系只有两种:1 [2-n] 和 [2-n] 1。 对与i = 2,[2-n]块又被分成2 [3-n] 两块,如此类推,即对于每个数(i<=n-1)都只有两种情况。
即可保证无环,其他情况均有环(因为会发出两条边,就算其他数都连一条边,边数会超过n-1,必定成环),无环情况数为2^(n-1)(对于每个数都有两种情况,即大数在左边,或者大数在右边)。
公式为:(n! - 2^n) ,按照公式计算即可。

代码:

#include 

using namespace std;

const int mod = 1e9 + 7;

int main() {
	int n;
	ios::sync_with_stdio(0);
	cin >> n;
	long long ans = 1 , t = 1;
	for(int i = n ; i > 0 ; i--) {
		ans = (ans * i) % mod;
	}
	for(int i = 0 ; i < n - 1 ; i++) {
		t = ( t * 2 ) % mod;
		
	}
	ans = (ans - t + mod ) % mod; 
	cout << ans << "\n";
	return 0;
}

你可能感兴趣的:(思维,codeforces)