牛客多校第一场E——ABBA(组合数,卡特兰数)

链接: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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值