【題目背景】c++
牆角那株海棠,是你種下的思念。測試
生死不能忘,高燭照容顏。spa
一曲江城唱晚,重憶當年坐燈前,3d
青衫中繡着你留下的線。code
——銀臨《江城唱晚》blog
【問題描述】get
扶蘇是個喜歡一邊聽古風歌一邊寫數學題的人,因此這道題實際上是五三原題。數學
歌曲中的主人公看着牆邊的海棠花,想起當年他其實和本身沿着牆邊種了一排海 棠,可是現在都已枯萎,只剩下那一株,寄託着對他深深的思念。it
沿着牆一共有 n 個位置能夠種下海棠花,主人公記得本身當年和他一共種下了 m 朵,因爲花的特性,海棠不能緊挨着種植,也就是兩朵海棠花之間最少間隔一個不種花 的空位置。可是她記不清當時海棠花具體是怎麼擺放的了,因此她想知道一共有多少方 案使得 m 朵海棠花都被種下且兩兩之間不是相鄰的。咱們將這 m 朵海棠花按照 1,2,3…m 的順序編號,兩個種花的方案不一樣當且僅當它們被種下的位置不一樣或者從左向 右數花的編號序列不一樣。io
爲了不輸出過大,答案對一個參數 p 取模
【輸入格式】
輸入文件名爲 ilove.in。
輸入文件中有且僅有一組數據,只有一行四個數字,分別表明 type,n,m,p。其中 type 是一個幫助你判斷測試點類型的參數,會在數據範圍中說明。
【輸出格式】
輸出文件名爲 ilove.out。
輸出一行一個數字,表明答案對 p 取模的結果。
【輸入輸出樣例 】
【數據規模與約定】
而後這套題的最後有句話:
(我恨了)
好了下面來講正解
SOLUTION:
首先,這是一道五三上的原題,因此它必定能夠用數學的方法來計算。
其實這是一道zhx問題,但當你找不到思路時,不妨在考場上打打表找規律
若是關心排列順序的話,每一個n與m的組合彷佛都對應一個排列數呢qwq
n=8,m=3對應排列數:C63,n=7,m=3對應排列數:C53
而樣例對應的C22,再仔細觀察,不難推測對應的排列數與n和m的取值有關,因而咱們大膽假設,在不考慮排列順序的前提下,這m盆花擺在n個位置的方案數是Cn-m+1m(好啦數學證實一下)
(對於任意兩盆海棠花,不能夠相鄰的種植,那麼每盆海棠花至關於佔據了兩個位置,由於會有一盆並不須要佔據,例如對於三盆花,須要佔據五個位置,因此咱們用n-m+1,直接刪去必定不能佔的位置,或者咱們能夠感性的理解成:先將這m盆花放到n-m+1個位置中(不考慮空隙),若是兩盆花相鄰了,就加一個空位在這兩盆花中間。那麼方案數就是將m盆花擺放在n-m+1個空位中的方案數)
求出了全部組合方案後,對於每種方案,都有Amm種不一樣的排列方法,因此最後答案就是:
Cn-m+1m*Amm
可是問題來了,看數據範圍:
這可了不起了,這怎麼算啊;
其實上面的式子能夠展開再化簡:
Cn-m+1m=(n-m+1)! /m!*(n-2m+1)!
Amm=m!;
Cn-m+1m*Amm=(n-m+1)!/(n-2m+1)!
=(n-m+1)*(n-m)*……*(n-2m+2);
因此這樣就能夠用很短的代碼直接for循環出來啦:
#include<bits/stdc++.h> using namespace std; inline long long read(){ long long ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch<='9'&&ch>='0') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } long long type,n,m,p; int main(){ type=read();n=read();m=read();p=read(); long long ans=1; for(int i=n-2*m+2;i<=n-m+1;i++) ans=(ans*i)%p; printf("%d",ans%p); return 0; }
畢竟zay寫了題解,因此咱們放一下:
end-