hdu5698 百度之星2016round2b第3題

這題首先是找規律推公式,而後就是組合數學的知識了。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;
}
相關文章
相關標籤/搜索