组合数取模
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
The input is given from Standard Input in the following format:
H W A BOutput
Print the number of ways she can travel to the bottom-right cell, modulo 109+7.
Sample Input 12 3 1 1Sample 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 210 7 3 4Sample Output 2
3570
There are 12 forbidden cells.
Sample Input 3100000 100000 99999 99999Sample Output 3
1Sample Input 4
100000 100000 44444 55555Sample 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); }
以上是关于组合数取模的主要内容,如果未能解决你的问题,请参考以下文章