1. 程式人生 > 其它 >題解 | #[HNOI2012]排隊#

題解 | #[HNOI2012]排隊#

站隊問題,插空法的變形

1.首先,如果只有兩種人的話我們直接使用插空法就好了
對於n個男生和m個女生,如果要求女生之間不站在一起,首先讓男生任意排列,在每個男生之間的空位(加上開頭和結尾)一共n+1個位置中任意選取m個位置來讓女生站隊,最後在對女生進行任意排列

即,公式如下: 2.下面我們來看本題,多出來一個老師這個群體,要求是老師也不能相鄰,因此我們需要想如何把三種群體轉換為兩種群體 思路來了:符合要求排列數==老師任意排列數-老師相鄰排列數 我們應當將老師看作男同學的一種,不考慮老師本身個體的的差異化。帶入上述公式符合要求排列數==老師任意排列數-老師相鄰排列數 老師任意排列的數量: 老師相鄰排列數(將老師們用繩子捆成一捆,看作一位男同學,這樣子就能保證相鄰了,只不過要注意捆在一起也有順序,要×2): 因此答案的數量為 化簡一下,用迴圈可以求解的形式表達出來就是 注意!!別忘記寫高精度!!!!
注意!!別忘記寫高精度!!!! 注意!!別忘記寫高精度!!!!

下面奉上程式碼:

//萬能標頭檔案
​#include<bits/stdc++.h>
using namespace std;
​
int ans[MAXN]={0};
int cnt=1;
//高精度乘法void multi(int x){
    for(int i=1;i<=cnt;i++){ 
​        ans[i]=x; 
​    } 
​    //進位 for(int i=1;i=10){
        ans[cnt+1]+=ans[cnt]/10,ans[cnt]%=10
; cnt++; } } ​int n,m; //所有乘法操作void op(){ multi(n*n+3n+2m); for(int i=1;i<=n+1;i++) ​ multi(i); ​ for(int i=n+4-m;i<=n+2;i++) ​ multi(i); ​} ​ ​int main(){ ​ memset(ans,0,sizeof(ans)); ​ ans[1]=1; ​ scanf("%d %d",&n,&m); ​ op(); ​
//輸出 for(int i=cnt;i>=1;i--){ printf("%d",ans[i]); } return 0; }