zoukankan      html  css  js  c++  java
  • FJNUOJ Yehan’s hole(容斥求路径数 + 逆元)题解

    Description

     

    Yehan is a angry grumpy rabbit, who likes jumping into the hole. This day,Yehan jumps again in the pit at home. Each time, he should jump from the hole at the coordinate (1,1) to (n,m), and he has to jump as the way : he can only jump (x, y) to (x+1, y) or (x, y+1). At his home, some holes are filled with water, he couldn’t jump in them. Yehan wants to know how many different way he could jump. If the paths of two ways are different, Yehan considers they are different.

    Input

     

    Multiple test dataThe first line of input contains two numbers n, m (2 <= n, m < 1e5)The second line of input contains a number q, the number of holes (q <= 15)The following q lines, the i-th line contains two numbers xi, yi (1 < x1 < x2 < x3 <……< xq < n) (1 < y1 < y2 < y3 < …… < yq < m)

    Output

     

    Output contains one line, the number of ways, because the result is too large, you should mod 1000000007

    题意:从(1,1)走到(n,m),其中有些格子有水坑不能走(保证水坑坐标(1 < x1 < x2 < x3 <……< xq < n) (1 < y1 < y2 < y3 < …… < yq < m),之前没看到这个坑死),问你有多少路径。

    思路:对于x*y的方格,从左上走到右下的路径数为:Cxx+y。这个高中组合应该讲过,因为横向必走x步,而且只要这x步确定了那么纵向怎么走必确定(可以自己试试),而横着走有x + y种可能。

    所以这道题我们要做的是总路径减去走水坑的路径。走水坑路径和总路径做法一样,但要用容斥。因为这里要组合数取模1e+7,所以还要用到逆元。一开始很傻比直接算逆元,其实这里直接打表阶乘的逆元,具体看下面参考内容。

    代码最后是数据。

    参考:【逆元】

    代码:

    #include<cstdio>
    #include<set>
    #include<vector>
    #include<cmath>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    typedef long long ll;
    using namespace std;
    const int maxn = 100000+5;
    const double INF = 0x3f3f3f3f;
    const ll MOD = 1000000007;
    struct node{
        int x, y;
    }p[20];
    ll ans, n, m;
    ll fac[maxn << 1], inv[maxn << 1];
    int q;
    int cmp(node a, node b){
        return a.x == b.x? a.y < b.y : a.x < b.x;
    }
    ll pmul(ll a, ll b){
        ll ans = 1;
        while(b){
            if(b & 1) ans = (ans * a) % MOD;
            a = a * a % MOD;
            b >>= 1;
        }
        return ans;
    }
    void init(){    //阶乘的逆元
        fac[0] = fac[1] = 1;
        for(ll i = 2; i <= 200000; i++)
            fac[i] = fac[i - 1] * i % MOD;
        inv[200000] = pmul(fac[200000], MOD - 2);
        for(ll i = 200000 - 1; i >= 0; i--)
            inv[i] = inv[i + 1] * (i + 1) % MOD;
    }
    ll C(ll x, ll y){   //组合逆元
        return (fac[y] * inv[y - x] % MOD) * inv[x] % MOD;
    }
    void dfs(int id, int pre, ll temp, int times){
        ll tmp1, tmp2;
        times++;
        tmp1 = (temp * C(p[id].x - p[pre].x, p[id].x - p[pre].x + p[id].y - p[pre].y)) % MOD;
        tmp2 = (tmp1 * C(n - p[id].x, n - p[id].x + m - p[id].y)) % MOD;
        if(times & 1) ans = (ans + tmp2) % MOD;
        else ans = (ans - tmp2) % MOD;
        for(int i = id + 1; i <= q; i++){
            dfs(i, id, tmp1, times);
        }
    }
    int main(){
        init();
        while(~scanf("%lld%lld", &n, &m)){
            scanf("%d", &q);
            p[0].x = 1, p[0].y = 1;
            for(int i = 1; i <= q; i++){
                scanf("%d%d", &p[i].x, &p[i].y);
            }
            ans = 0;
            for(int i = 1; i <= q; i++){
                dfs(i, 0, 1, 0);    //now pre mul time
            }
            printf("%lld
    ", ((C(n - 1, n + m - 2) - ans) % MOD + MOD) % MOD);
        }
        return 0;
    }
    
    /*
    input
    6122 61753
    2
    1957 18165
    4448 30108
    91557 89797
    9
    11169 5062
    30315 34046
    37127 36827
    44369 50521
    62770 58297
    64008 62857
    79378 67405
    88132 86222
    89483 87524
    74355 52758
    12
    1193 7922
    11316 9175
    19053 11037
    38189 11344
    38317 15083
    40095 19756
    41161 24874
    47120 30594
    50188 34496
    51327 36374
    53291 50539
    66554 51069
    56766 19695
    7
    2012 1210
    12159 11135
    18759 13249
    40035 13828
    41494 13959
    45882 18241
    49535 19379
    31178 59737
    7
    698 14597
    7306 14856
    8198 19316
    9000 45862
    10879 53006
    12002 54423
    24634 58820
    81872 8035
    4
    32720 1451
    40464 4253
    51261 6151
    72014 6683
    21393 42250
    13
    422 1192
    478 2683
    3265 3684
    4422 4366
    4760 13041
    6586 22349
    6803 24676
    7273 25162
    8875 29191
    13875 32524
    14791 33611
    17168 34162
    21102 39838
    5572 26973
    9
    1760 697
    2106 4583
    2141 6788
    2438 6790
    3811 7301
    4293 11943
    4607 15554
    5164 15929
    5529 18282
    
    output
    390661224
    872660150
    97529549
    252410050
    742624594
    697140589
    674450439
    109291758
    */
  • 相关阅读:
    PE文件捆绑实现二:(远程线程注入)
    C++中Vector清空
    ttrss更新到最新版本后发访问非80和443端口规避
    Git配置https_proxy访问github失败
    Haproxy配置拦截指定src的连接
    synology git管理程序添加
    ActiveMQ深入浅出系列 (一)
    sl4fj日志级别
    HTTP上传文件解析
    linux下jcmd无法获取jvmdump
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9588805.html
Copyright © 2011-2022 走看看