codeforces 559C|51nod1486 Gerald and Giant Chess(组合数学+逆元)

codeforces 559C|51nod1486

题目

有中文题目

思路

http://blog.csdn.net/winddreams/article/details/47058209
这位博主讲的很清楚了,还有逆元的技巧。
(其间还了解了一下Lucas定理

代码

#include <cstdio>  
    #include <cstring>  
    #include <algorithm>  
    using namespace std ;  
    #define LL __int64  
    const LL MOD = 1e9+7 ;  
    struct node{  
        LL x , y ;  
    }p[3100];  
    LL h , w , n ;  
    LL fac[310000] , inv[310000] ;  
    LL sum[3100] ;  
    int cmp(node a,node b) {  
        return a.x < b.x || (a.x == b.x && a.y < b.y) ;  
    }  
    LL pow(LL x,LL k) {  
        LL ans = 1 ;  
        while( k ) {  
            if( k&1 ) ans = ans*x%MOD ;  
            k = k>>1 ;  
            x = (x*x)%MOD ;  
        }  
        return ans ;  
    }  
    void init() {  
        LL i , j , c ;  
        fac[0] = inv[0] = 1 ;  
        for(i = 1 ; i <= h+w ; i++)  
            fac[i] = (fac[i-1]*i)%MOD ;  
        c = max(h,w) ;  
        inv[c] = pow(fac[c],MOD-2) ;  
        for(i = c-1 ; i > 0 ; i--) {  
            inv[i] = inv[i+1]*(i+1)%MOD ;  
        }  
    }  
    int main() {  
        LL i , j ;  
        LL ans ;  
        while( scanf("%I64d %I64d %I64d", &h, &w, &n) != EOF ) {  
            init() ;  
            for(i = 0 ; i < n ; i++)  
                scanf("%I64d %I64d", &p[i].x, &p[i].y) ;  
            p[n].x = h ; p[n++].y = w ;  
            sort(p,p+n,cmp) ;  
            int x1 , y1 , x2 , y2 ;  
            for(i = 0 ; i < n ; i++) {  
                x1 = p[i].x-1 ; y1 = p[i].y-1 ;  
                sum[i] = fac[x1+y1]*inv[x1]%MOD*inv[y1]%MOD ;  
                for(j = 0 ; j < i ; j++) {  
                    if( p[j].x <= p[i].x && p[j].y <= p[i].y ) {  
                        x2 = x1 - p[j].x+1 ; y2 = y1 - p[j].y+1 ;  
                        sum[i] = (sum[i]-fac[x2+y2]*inv[x2]%MOD*inv[y2]%MOD*sum[j]%MOD)%MOD ;  
                        if( sum[i] <= 0 ) sum[i] = (sum[i]+MOD)%MOD;  
                    }  
                }  
            }  
            printf("%I64d\n", sum[n-1]) ;  
        }  
        return 0 ;  
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值