hdu2068 錯排公式
阿新 • • 發佈:2018-11-19
一個有n個元素的排列,若一個排列中所有的元素都不在自己原來的位置上,那麼這樣的排列就稱為原排列的一個錯排,n個元素的錯排數記為D(n)。那麼對於這樣的排列D(n)有多少種呢?我們一步一步進行分析:
首先,對於D(n),有1~n這樣n個元素錯排,所以對於第一個元素①,它現在可能的位置有(n-1)個,倘若它在第k個元素的位置上,對於第k個元素而言,它所在的位置就有兩種可能:第一種,它處在非第一個元素①位置上,所以對於接下來的排列就相當於是n-1個元素的錯排,即D(n-1);第二種,它處在第一個元素①的位置上,所以在排列D(n)中有兩個元素找到了位置,那麼接下來的佇列就相當於是n-2個元素的錯排。因此,對於D(n)都有D(n)=(n-1)*(D(n-1)+D(n-2)) 特殊的,D(1)=0,D(2)=1。
Problem Description
今年暑假杭電ACM集訓隊第一次組成女生隊,其中有一隊叫RPG,但竟然不知道RPG的n個人具體是誰誰。RPG給他機會讓他猜猜,......女生們只要求他答對一半或以上就算過關,請問有多少組答案能使他順利過關。
Input
輸入的資料裡有多個case,每個case包括一個n,代表有幾個女生,(n<=25), n = 0輸入結束。
Sample Input
1 2 0
Sample Output
1 1
#include "pch.h" #pragma warning (disable:4996) #include<stdio.h> #include <iostream> #include<cstring> #include<algorithm> #include<vector> #include<queue> using namespace std; long long comb[100][100]; long long wcomb[100]; long long com(int a, int b) { if (comb[a][b] >= 0) return comb[a][b]; long long res; if (a == b || b == 0) return res = 1; else res = com(a - 1, b) + com(a - 1, b - 1); return comb[a][b] = res; } long long wcom(int b) { if (b == 1) return wcomb[1] = 0; if (b == 2) return wcomb[2] = 1; long long res; wcomb[b] = (b - 1)*(wcom(b - 1) + wcom(b - 2)); return wcomb[b]; } int main() { //freopen("datain.txt", "r", stdin); int a; while (~scanf("%d", &a)) { if (!a) break; memset(comb, -1, sizeof(comb)); memset(wcomb, -1, sizeof(wcomb)); long long sum = 1;//全部正確的情況:1 //要求至少猜對一半或以上,則允許錯排的個數為a/2 //小數部分抹去 //當女生有3個的時候,a/2=1,但是一個女生無法錯排 //錯排的最小數字應該是2 for (int b = a / 2;b >= 2;b--) { //當然此處寫成b>=1也沒關係,因為wcom(1)==0; sum += com(a, b)*wcom(b); } cout << sum << endl; } }