组合数取模

Posted 贱人方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了组合数取模相关的知识,希望对你有一定的参考价值。

We have a large square grid with H rows and W columns. Iroha is now standing in the top-left cell. She will repeat going right or down to the adjacent cell, until she reaches the bottom-right cell.

However, she cannot enter the cells in the intersection of the bottom A rows and the leftmost B columns. (That is, there are A×B forbidden cells.) There is no restriction on entering the other cells.

Find the number of ways she can travel to the bottom-right cell.

Since this number can be extremely large, print the number modulo 109+7.


Constraints
  • 1≦H,W≦100,000
  • 1≦A<H
  • 1≦B<W
Input

The input is given from Standard Input in the following format:

H W A B
Output

Print the number of ways she can travel to the bottom-right cell, modulo 109+7.

Sample Input 1
2 3 1 1
Sample Output 1
2

We have a 2×3 grid, but entering the bottom-left cell is forbidden. The number of ways to travel is two: "Right, Right, Down" and "Right, Down, Right".

Sample Input 2
10 7 3 4
Sample Output 2
3570

There are 12 forbidden cells.

Sample Input 3
100000 100000 99999 99999
Sample Output 3
1
Sample Input 4
100000 100000 44444 55555
Sample Output 4
738162020

【分析】给你一个H*W的网格,起点在(1,1),终点在(H,W),每一步只能向下或者向右,再给你左下角的一片区域(a*b),a行b列,此区域不能走,问从起点走到终点有多少方案数。
枚举第H-a行的b+1-->w列,然后组合数求解。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <stack>
#include <queue>
#include <vector>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
typedef long long ll;
using namespace std;
const int N = 2e5+10;
const int M = 24005;
const int MOD = 1e9+7;
int h,w,a,b;
ll f[N];
ll finv[N];

ll c(ll n,ll m) {
    ll ret=f[n];
    ret=(ret*finv[n-m])%MOD;
    ret=(ret*finv[m])%MOD;
    return ret;
}

ll calc(ll i,ll j) {
    return c(i+j-2,i-1);
}

ll qp(ll x,ll n) {
    ll ret=1;
    while (n) {
        if (n&1) ret=(ret*x)%MOD;
        n=n>>1;
        x=(x*x)%MOD;
    }
    return ret;
}

int main() {
    scanf("%d%d%d%d",&h,&w,&a,&b);
    memset(f,0,sizeof(f));
    memset(finv,0,sizeof(finv));
    f[0]=finv[0]=1;
    for (int i=1; i<=200000; i++) {
        f[i]=(f[i-1]*i)%MOD;
        finv[i]=qp(f[i],MOD-2);
    }
    ll ans=0;
    for (int i=1; i<=w-b; i++) {
        ans=(ans+(calc(a,i)*calc(h-a,w-i+1))%MOD)%MOD;
        ans=(ans+MOD)%MOD;
    }
    printf("%lld\n",ans);
}

 

以上是关于组合数取模的主要内容,如果未能解决你的问题,请参考以下文章

组合数取模(Lucas)

对组合数取模

组合数取模

排列组合+组合数取模 HDU 5894

组合数取模

组合数取模(转载)