链接:https://ac.nowcoder.com/acm/contest/881/E
来源:牛客网
ABBA
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld
题目描述
Bobo has a string of length 2(n + m) which consists of characters `A` and `B`. The string also has a fascinating property: it can be decomposed into (n + m) subsequences of length 2, and among the (n + m) subsequences n of them are `AB` while other m of them are `BA`.
Given n and m, find the number of possible strings modulo (109+7)(10^9+7)(109+7).
输入描述:
The input consists of several test cases and is terminated by end-of-file. Each test case contains two integers n and m. * 0≤n,m≤1030 \leq n, m \leq 10^30≤n,m≤103 * There are at most 2019 test cases, and at most 20 of them has max{n,m}>50\max\{n, m\} > 50max{n,m}>50.
输出描述:
For each test case, print an integer which denotes the result.
示例1
输入
复制
1 2 1000 1000 0 0
输出
复制
13 436240410 1
题解是用dp做的,但其实可以用类似卡特兰数的思想来处理这个题。
我们都知道卡特兰数有一个很经典的例子,排队找零钱的那个问题,仔细想想,这个问题也差不多,如果需要有n个AB,那就需要有n个A在n个B的前面,同理,如果需要m个B,就需要有m个B在m个A的前面。
用这种思路想的话,可以参考一下这位大神的博客:点我看大神博客
容易理解,通俗易懂,还可以加深对这类问题的理解。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <cmath>
#define int long long
const int maxn=1e4+10;
const int mod=1e9+7;
int f[maxn];
int f0[maxn];
int inv[maxn];
void init()
{
f[0]=f[1]=1;
f0[0]=f0[1]=1;
inv[0]=inv[1]=1;
for(int i=2;i<=maxn;i++)
{
//阶乘数
f[i]=f[i-1]*i%mod;
//i在mod意义下的逆元
f0[i]=(mod-mod/i)*f0[mod%i]%mod;
//阶乘逆元
inv[i]=inv[i-1]*f0[i]%mod;
}
}
//求阶乘数C(a,b)在mod意义下的值
int C(int a,int b)
{
if(a<0)return 0;
if(a==0)return 1;
return f[b]*inv[a]%mod*inv[b-a]%mod;
}
int solve(int n,int m){
return (f[2*(n+m)]*inv[n+m]%mod*inv[n+m]%mod-C(m-1,2*(n+m))+mod-C(n-1,2*(n+m))+mod)%mod;
}
signed main(){
init();
int n,m;
while(scanf("%lld%lld",&n,&m)!=EOF){
printf("%lld\n",solve(n,m));
}
return 0;
}