题目
有 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 2∗3+1∗3=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 C21∗C31+C22∗C32=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} Cn1∗Cm1+Cn2∗Cm2+...+Cnn∗Cmn
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} Cn0∗Cm0+Cn1∗Cm1+Cn2∗Cm2+...+Cnn∗Cmn=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+mn−1=n!m!(n+m)!−1
6.程序开始打表,得到阶乘的表,然后可以直接得到分子,然后乘分母的逆元就可以得到答案
代码
#include <stdio.h>
#include<bits/stdc++.h>
#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;
}