码迷,mamicode.com
首页 > 其他好文 > 详细

cf559c

时间:2015-08-06 02:02:29      阅读:810      评论:0      收藏:0      [点我收藏+]

标签:

组合数学DP

技术分享
#include <cstdio>
#include <algorithm>
using namespace std;

#define d(x) 
#define LL long long

const int MAX_N = 2020;
const int MAX_M = (int)(2e5) + 20;
const int MOD = (int)(1e9) + 7;

int row_num, col_num;
int n;
pair<int, int> point[MAX_N];
long long dp[MAX_N];

void input()
{
    scanf("%d%d%d", &row_num, &col_num, &n);
    for (int i = 0; i < n; i++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        point[i] = make_pair(a, b);
    }
    point[n++] = make_pair(row_num, col_num);
    point[n++] = make_pair(1, 1);
    for (int i = 0; i < n; i++)
    {
        point[i].first--;
        point[i].second--;
    }
}

LL multi_mod(LL a, LL b, LL c)
{    //返回(a*b) mod c,a,b,c<2^63
    a %= c;
    b %= c;
    LL ret = 0;
    while (b)
    {
        if (b & 1)
            ret = (ret + a) % c;
        a <<= 1;
        a %= c;
        b >>= 1;
    }
    return ret;
}

LL pow_mod(LL x, LL n, LL mod)
{  //返回x^n mod c ,非递归版
    x %= mod;
    if (n == 1)
        return x;
    LL ret = 1;
    while (n)
    {
        if (n & 1)
            ret = multi_mod(ret, x, mod);
        n >>= 1;
        x = multi_mod(x, x, mod);
    }
    return ret;
}

long long get_inverse(long long a)
{
    return pow_mod(a, MOD - 2, MOD);
}

long long factorial[MAX_M];
long long inverse[MAX_M];

void init_comb(int n)
{
    factorial[0] = 1;
    for (int i = 1; i <= n; i++)
    {
        factorial[i] = factorial[i - 1] * i;
        factorial[i] %= MOD;
    }
    inverse[n] = get_inverse(factorial[n]);
    for (int i = n - 1; i >= 0; i--)
    {
        inverse[i] = inverse[i + 1] * (i + 1);
        inverse[i] %= MOD;
    }
}

long long comb(long long a, long long b)
{
    long long ret = factorial[a] * inverse[a - b];
    ret %= MOD;
    ret *= inverse[b];
    ret %= MOD;
    return ret;
}

int main()
{
    init_comb(200000);
    input();
    sort(point, point + n);
    dp[0] = 1;
    for (int i = 1; i < n; i++)
    {
        dp[i] = comb(point[i].first + point[i].second, point[i].second);
        for (int j = 1; j < i; j++)
        {
            if (point[j].first <= point[i].first && point[j].second <= point[i].second)
            {
                long long a = point[i].first - point[j].first;
                a += point[i].second - point[j].second;

                long long b = point[i].second - point[j].second;

                dp[i] -= (dp[j] * comb(a, b)) % MOD;
                dp[i] += MOD;
                dp[i] %= MOD;
            }
        }
        d(printf("dp[%d] = %d\n", i, (int)dp[i]));
    }
    printf("%d\n", (int)dp[n - 1]);
    return 0;
}
View Code

 

cf559c

标签:

原文地址:http://www.cnblogs.com/rainydays/p/4706219.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!