问题 B: 计数(组合数学+思维+线性求逆元)

问题 B: 计数(组合数学+思维+线性求逆元)

题目描述

Alice和Bob在平面直角坐标系中下棋。Alice的棋子初始时在(0,0)位置,要走到(a,b)位置;Bob的棋子初始时在(c,0)位置,要走到(a,d)位置。棋子只能沿x轴或y轴正方向移动若干个单位长度,问有多少种移动方案使两颗棋子的移动路径不相交。

输入

输入一行4个正整数,依次为a,b,c,d。

输出

输出总方案数对质数 100000007 取模的结果。

样例输入 Copy

3 2 1 1

样例输出 Copy

6

提示

【样例解释】
A 走(0,0)  →  (0,2)  →  (3,2)  时, B 有 3 种走法:
(1,0)  →  (1,1)  →  (3,1)
(1,0)  →  (2,0)  →  (2,1)  →  (3,1)
(1,0)  →  (3,0)  →  (3,1)
A  走(0,0)  →  (0,1)  →  (1,1)  →  (1,2)  →  (3,2)时, B 有 2 种走法。
A  走(0,0)  →  (0,1)  →  (2,1)  →  (2,2)  →  (3,2)时, B 有 1 种走法。

【数据范围】
对于 50%的数据, a + b <= 20。
对于 70%的数据, a + b <= 2e4。
对于 100%的数据, a + b <= 2e5  且 a > c, b > d。

思路:记得做过。首先是A的终点在B的终点的上方。
如不考虑相交的话,答案即为C(a+b,a)*C(a+d-c,d)。考虑相交的情况,
交点只会出现再(c,0)-(a,d)的矩阵中,我们把彼此的终点换一下,这样就必然相交了。
再减去,C(a+d,a)*C(a+b-c,b)就是答案。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
  
#define rep(i , a , b) for(register int i=(a);i<=(b);i++)
#define per(i , a , b) for(register int i=(a);i>=(b);i--)
#define ms(s) memset(s, 0, sizeof(s))
  
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int , int> pi;
typedef unordered_map<int,int> un_map;
template<class T>
inline void read (T &x) {
    x = 0;
    int sign = 1;
    char c = getchar ();
    while (c < '0' || c > '9') {
        if ( c == '-' ) sign = - 1;
        c = getchar ();
    }
    while (c >= '0' && c <= '9') {
        x = x * 10 + c - '0';
        c = getchar ();
    }
    x = x * sign;
}
  
const int maxn = 5e5+10;
const int inf = 0x3f3f3f3f;
const ll INF = ll(1e18);
const int mod = 100000007;
const double PI = acos(-1);
#define LOCAL
  
ll n,m;
ll f[maxn],inv[maxn];
  
  
void init() {
    inv[0]=1;
    inv[1]=1;
    f[1]=1;
    f[0]=1;
    rep(i,2,maxn-5) {
        f[i]=f[i-1]*i%mod;
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    }
  
    rep(i,2,maxn-5) {
        inv[i]=inv[i]*inv[i-1]%mod;
    }
}
  
ll C(ll p,ll q) {
    return f[p]*inv[q]%mod*inv[p-q]%mod;
}
 
  
int main(int argc, char * argv[])
{
    init();
    ll a,b,c,d;
    read(a);read(b);read(c);read(d);
    ll ans = (C(a+b,a)%mod*C(a+d-c,d)%mod-C(a+d,a)%mod*C(a+b-c,b)%mod+mod)%mod;
    printf("%lld\n",ans);
    return 0;
}
发布了259 篇原创文章 · 获赞 2 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/dy416524/article/details/105733992