题目链接
题目大意
思路
通过找规律发现,只有当一个排列中的一个数的两边都有1个比他大的数时才可能有环,比如说312,1432,如果没有,就不可能有环,比如1234。
然后打表,发现,
n = 3, 有2种,
n = 4, 有16种,
n = 5, 有104种,
n = 6, 有688种,
n = 3, 共有6种, 6 - 2 = 4 =
2
3
−
1
2^{3-1}
23−1
n = 4, 共有24种,24 - 16 = 8 =
2
4
−
1
2^{4-1}
24−1
n = 5, 共有120种,120 - 104 = 16 =
2
5
−
1
2^{5-1}
25−1
n = 6, 共有720种,720 - 688 = 32 =
2
6
−
1
2^{6-1}
26−1
我们又知道,一个数所有的排列有n!种,有环的排列方式的总数就是 n ! − 2 n − 1 n! - 2^{n-1} n!−2n−1
代码
#include<bits/stdc++.h>
#define int long long
const int mod = 1e9 + 7;
using namespace std;
signed main()
{
int n;
cin >> n;
int ans = 1;
for (int i = 1; i <= n; i ++ )
{
ans *= i;
ans %= mod;
}
int mm = 1;
for (int i = 2; i <= n; i ++ )
{
mm *= 2;
mm %= mod;
}
ans -= mm;
ans %= mod;
ans = (ans + mod) % mod; //因为之前有 - ,所以要先加模数,防止有负数
cout << ans;
return 0;
}
//打表找规律
//#include<bits/stdc++.h>
//#define int long long
//using namespace std;
//signed main()
//{
// int n;
// cin >> n;
// int a[n + 10];
// for (int i = 1; i <= n; i ++ )
// {
// a[i] = i;
// }
// int cnt=0;
// do{
// for (int i = 1; i <= n; i ++ )
// {
// int ans = 0;
// for (int j = i - 1; j >= 1; j -- )
// {
// if (a[i] < a[j])
// {
// ans ++;
// break;
// }
// }
// for (int j = i + 1; j <= n; j ++ )
// {
// if (a[i] < a[j])
// {
// ans ++;
// break;
// }
// }
// if (ans == 2)
// {
// cnt ++;
cout << cnt;
// cnt %= (int)1e9+7;
// break;
// for (int j = 1; j <= n; j ++ )
// {
// cout << a[i] << " ";
// }
// cout << endl;
// }
// }
// }while(next_permutation(a + 1, a + 1 + n));
// cout << cnt << endl;
// return 0;
//}