计蒜客 - T3144

题目

有 n 个不同的气球和 m 个不同的重物,每个气球都可以提供 1N 的升力(竖直向上),每个重物都会受到 1N

的重力(竖直向下)。

现要选出若干个气球和若干个重物,将他们固定在一起,并且使得固定之后的整体受力平衡,请问共有多少种满足条件的方案?
输入格式

输入数据第一行一个正整数 T

,表示测试数据组数

接下来 T
行,每行包含两个空格隔开的正整数 n 和 m

输出格式

输出 T
行,每行包括一个数字,表示答案除以 109+7

的余数
数据范围

对于 20%
的数据,m=1

对于 60%
的数据,1≤n,m≤103,1≤T≤104

对于全部的数据,1≤n,m≤106
,1≤T≤106

Sample Input

1
2 3

Sample Output

9

Sample Explain

不妨用 b1,b2

表示两个气球,用 w1,w2,w3

表示三个重物

下面每行都描述了一个符合要求的方案

b1,w1

b1,w2

b1,w3

b2,w1

b2,w2

b2,w3

b1,b2,w1,w2

b1,b2,w1,w3

b1,b2,w2,w3

解题

1.从例子中我们可以得到公式: 2 ∗ 3 + 1 ∗ 3 = 9 2*3+1*3=9 23+13=9
2.上面可以化成 C 2 1 ∗ C 3 1 + C 2 2 ∗ C 3 2 = 9 \mathrm{C}_2^{1}*\mathrm{C}_3^{1}+\mathrm{C}_2^{2}*\mathrm{C}_3^{2}=9 C21C31+C22C32=9
3.所以我们可以得到一个通式:当n<=m,答案为 C n 1 ∗ C m 1 + C n 2 ∗ C m 2 + . . . + C n n ∗ C m n \mathrm{C}_n^{1}*\mathrm{C}_m^{1}+\mathrm{C}_n^{2}*\mathrm{C}_m^{2}+...+\mathrm{C}_n^{n}*\mathrm{C}_m^{n} Cn1Cm1+Cn2Cm2+...+CnnCmn
4.这里就要用到lucas定理,得到以下化简:
C n 0 ∗ C m 0 + C n 1 ∗ C m 1 + C n 2 ∗ C m 2 + . . . + C n n ∗ C m n = C n + m n \mathrm{C}_n^{0}*\mathrm{C}_m^{0}+\mathrm{C}_n^{1}*\mathrm{C}_m^{1}+\mathrm{C}_n^{2}*\mathrm{C}_m^{2}+...+\mathrm{C}_n^{n}*\mathrm{C}_m^{n}=\mathrm{C}_{n+m}^{n} Cn0Cm0+Cn1Cm1+Cn2Cm2+...+CnnCmn=Cn+mn
5.所以我们要的结果就是 C n + m n − 1 = ( n + m ) ! n ! m ! − 1 \mathrm{C}_{n+m}^{n}-1=\frac{(n+m)!}{n!m!}-1 Cn+mn1=n!m!(n+m)!1
6.程序开始打表,得到阶乘的表,然后可以直接得到分子,然后乘分母的逆元就可以得到答案

代码

#include 
#include
#define ll long long
using namespace std;
const int mod = 1e9+7;
ll ff[2000005];  //n+m
ll quick_pow(ll x,ll n,ll m)
{
	ll res = 1;
	while(n > 0)
	{
		if(n & 1)
            res = res * x % m;
		x = x * x % m;
		n >>= 1;
	}
	return res;
}
ll inv(ll a)
{
    return quick_pow(a,mod - 2,mod);
}

int main()
{
    ll m,n;
    ff[0]=1;
    for(int i=1;i<=2000000;i++) //打表
        ff[i]=(ff[i-1]*i)%mod;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld",&n,&m);
        ll ans=((ff[n+m]*inv(ff[n]))%mod*inv(ff[m]))%mod; //一定要每一步%mod
        printf("%lld\n",ans-1);
    }
    return 0;
}

你可能感兴趣的:(c++)