這題首先是找規律推公式,而後就是組合數學的知識了。ios
題目是問到第n行第m列的格式有幾種方案,咱們能夠用手算的方法列出當n和m比較小時的全部答案spa
好比我列出如下8*8的矩陣code
924 462 210 84 28 7 1 0 462 252 126 56 21 6 1 0 210 126 70 35 15 5 1 0 84 56 35 20 10 4 1 0 28 21 15 10 6 3 1 0 7 6 5 4 3 2 1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1
矩陣上的數表示從那個位置到最右下角一共有多少種方案。blog
求每一個位置的值也簡單,就是把它右下角的全部數加起來便可。數學
那麼,把這個矩陣倒過來看,就是想要的結果矩陣了。string
規律也很容易發現,首先,矩陣是對稱的,因此我是隻考慮m>=n的狀況。it
而後,能夠發現每一個位置的數就是一個組合數C(m + n - 4, n - 2)io
最後就是求組合數取模了,C(m + n - 4, n - 2) % function
然而,多年沒作題的我,並不會組合數取模。找了之前的模板,是竹教主寫的,看了好半天才明白,等我打完的時候,比賽剛結束。模板
比賽結束後交了一次,果真a了T_T
如下是代碼
/* * baidu/win.cpp * Created on: 2016-5-22 * Author : ben */ #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <iostream> #include <algorithm> #include <queue> #include <set> #include <map> #include <stack> #include <string> #include <vector> #include <deque> #include <list> #include <functional> #include <numeric> #include <cctype> using namespace std; typedef long long LL; LL Ext_gcd(LL a, LL b, LL &x, LL &y) { if (b == 0) { x = 1, y = 0; return a; } LL ret = Ext_gcd(b, a % b, y, x); y -= a / b * x; return ret; } LL Inv(LL a, int m) { ///求除數a對m的逆元; LL d, x, y, t = (LL) m; d = Ext_gcd(a, t, x, y); if (d == 1) return (x % t + t) % t; return -1; } void work(int n, int m) { int i; const int mod = 1000000007; LL sum = 1; for (i = n - m + 1; i <= n; i++) { sum *= (LL) i; sum %= mod; } LL tmp = 1; for (i = 2; i <= m; i++) tmp *= i, tmp %= mod; sum *= Inv(tmp, mod); sum %= mod; printf("%I64d\n", sum); } int main() { int n, m; while (scanf("%d%d", &n, &m) == 2) { if (m < n) { int tmp = m; m = n; n = tmp; } work(m + n - 4, n - 2); } return 0; }