CF888 D. Almost Identity Permutations(數學)

題目傳送

題意:給定n,k,求至少有n-k個ai=i的排列數

分析:
爲方便,用n-k代替k
比如n = 5,k = 1
先看有且僅有1個ai=i的情況:
 有且僅有1個ai=i有C51C_5^1種情況,以a1=1爲例
 剩下的四個位置,不能出現ai=i,第二位可以填3 4 5,第三位可以2 4 5,在二三位確定後,四五位自然確定
 ans=C51C_5^1 * 333*3
有且僅有2個ai=i時:
 兩個位置確定的可能:C52C_5^2 以a1=1,a2=2爲例
 第三個位置可以填4 5,四五位置確定
 ans=C52C_5^2 * 2
有且僅有3個位置確定時,剩下兩個位置只能有一種情況
4個位置確定時,第五個位置自然確定

所以我們可以得出一個規律:ans=C51C_5^1*(511)(512)(5-1-1)^(5-1-2)++C52C_5^2*(521)(522)(5-2-1)^(5-2-2)++C53C_5^3*(531)(532)(5-3-1)^(5-3-2)++ 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章