hdu 5698 組合數
阿新 • • 發佈:2019-01-30
瞬間移動
Problem Description
有一個無限大的矩形,初始時你在左上角(即第一行第一列),每次你都可以選擇一個右下方格子,並瞬移過去(如從下圖中的紅色格子能直接瞬移到藍色格子),求到第n行第m列的格子有幾種方案,答案對1000000007取模。
Input多組測試資料。
兩個整數n,m(2≤n,m≤100000)
Output一個整數表示答案
Sample Input4 5Sample Output
10
Source
分析:
畫幾個數之後就可以發現規律了,可以看出是一個傾斜45度的楊輝三角,每個位置的的數相當於:從楊輝三角第(n+m-4)層,取m-2個數。
因為會有除法取模,所以要用逆元。
有兩個公式:
這兩個公式實際上是等價的,只是用程式碼實現的時候會有所差別。
我是用第二個寫的:
當然逆元也有很多種實現方法:#include<cstdio> #include<cstring> const long long mod=1000000007; typedef long long ll; const int N=100002; ll inv[N]; int main() { int n,m; inv[1]=1; for(int i=2;i<N;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod; while(~scanf("%d%d",&n,&m)){ if(n==1||m==1){ printf("0\n");continue; } n=n+m-4; m=m-2; ll ans=1; for(int i=1;i<=m;i++){ ans=(ans*(ll)(n-i+1))%mod; ans=(ans*inv[i])%mod; } printf("%lld\n",ans); } return 0; }
可以用擴充套件歐幾里德定理,費馬小定理(這需要快速冪實現),或者上面那個遞推公式。
對於這題,是用楊輝三角來做的,也有人的思路是:
給我們一個座標,我們可以得出可以移動到的區域即(n-2)*(m-2)。列舉要在這個區域停留幾次,C(y,k),表示從y列中選k列去停,C(x,k)表示從x行中選哪k行去停。所以乘積累加即為結果。
這種《問題分解》的思想是值得學習的,就像UVa 11134這題的思想是一致的。