Iroha and a Grid(组合数学)

Iroha and a Grid

题目描述

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

输入

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

H W A B

输出

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

样例输入

2 3 1 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".

来源

题意:n*m矩阵 左下方A*B为禁区,每次可以走下或者左,n,m<=1e5,问从左上到右下不经过禁区时的方案数?

题解:就是找路吧 以为可以动态规划但是数据太大 数组开不了 看了下大佬的 原来可以用组合数 若无禁区,则方案数为C(n+m-2,n-1)

有禁区时 每个合法路径都会到达(n-A,i)i>B 即n-A行的某一列上.则每个合法路径都可以分成两段,(1,1)->(n-A,i),(n-A,i)->(n,m) (i>B)

注意枚举到(n-A,i)不能向右移动,否则重复枚举.所以路径变为三段.
这个题目因为是排列组合涉及到除法,所以需要使用逆元。

链接 逆元


#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <map>
#include <set>
#include <queue>
using namespace std;
#define lowbit(x) (x&(-x))
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
#define MAX 100000000000000000
#define MOD 1000000007
#define pi acos(-1.0)
#define ei exp(1)
#define PI 3.141592653589793238462
#define INF 0x3f3f3f3f3f
#define mem(a) (memset(a,0,sizeof(a)))
typedef long long ll;
ll gcd(ll a,ll b){
    return b?gcd(b,a%b):a;
}
bool cmp(int x,int y)
{
    return x>y;
}
const int N=2e5+20;
const ll mod=1e9+7;
ll f[N],n,m,A,B;
ll powmod(ll x,ll n)
{
    ll s=1;
    while(n){
        if(n&1)
            s=(s*x)%mod;
        x=(x*x)%mod;
        n>>=1;
    }
    return s;
}
ll C(ll n,ll m)
{
    ll a=f[n];
    ll b=(f[m]*f[n-m])%mod;
    return (a*powmod(b,mod-2))%mod;
}
int main()
{
    f[0]=1;
    for(ll i=1;i<N;i++)
        f[i]=(f[i-1]*i)%mod;
    while(cin>>n>>m>>A>>B){
        ll res=0;
        for(ll i=B+1;i<=m;i++){
            ll tmp=(C(i-1+n-A-1,n-A-1)*C(m-i+A-1,m-i))%mod;
            res=(res+tmp)%mod;
        }
        cout<<res<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41021816/article/details/80383253