题意:给定n,k,求至少有n-k个ai=i的排列数
分析:
为方便,用n-k代替k
比如n = 5,k = 1
先看有且仅有1个ai=i的情况:
有且仅有1个ai=i有
C
5
1
C_5^1
C51种情况,以a1=1为例
剩下的四个位置,不能出现ai=i,第二位可以填3 4 5,第三位可以2 4 5,在二三位确定后,四五位自然确定
ans=
C
5
1
C_5^1
C51
∗
*
∗
3
∗
3
3*3
3∗3
有且仅有2个ai=i时:
两个位置确定的可能:
C
5
2
C_5^2
C52 以a1=1,a2=2为例
第三个位置可以填4 5,四五位置确定
ans=
C
5
2
C_5^2
C52
∗
*
∗ 2
有且仅有3个位置确定时,剩下两个位置只能有一种情况
4个位置确定时,第五个位置自然确定
所以我们可以得出一个规律:ans= C 5 1 C_5^1 C51 ∗ * ∗ ( 5 − 1 − 1 ) 2 (5-1-1)^2 (5−1−1)2 + + + C 5 2 C_5^2 C52 ∗ * ∗ ( 5 − 2 − 1 ) 1 (5-2-1)^1 (5−2−1)1 + + + C 5 3 C_5^3 C53 ∗ * ∗ ( 5 − 3 − 1 ) 0 (5-3-1)^0 (5−3−1)0 + + + 1
上代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <vector>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int inf = 0x3f3f3f3f;
const ll Inf = 1e18;
ll zuhe(ll n, ll m) //组合数
{
if (m < n - m) m = n - m;
ll ret = 1;
for (int i = m + 1; i <= n; i++) ret *= i;
for (int i = 2; i <= n - m; i++) ret /= i;
return ret;
}
int main(void)
{
int n, k;
ll ans = 0;
cin >> n >> k;
k = n - k;
while (n - k >= 2) {
ans += zuhe(n, k) * pow(n - k - 1, n - k - 2);
k++;
}
ans += 1;
cout << ans << endl;
return 0;
}
因篇幅问题不能全部显示,请点此查看更多更全内容