[CSP-S模拟测试]:排列组合(数学 or 找规律)
题目描述
$T$组数据,每次给定$n$,请求出下式的值,对$10^9+7$取模:
$$C_n^0\times C_n^0+C_n^1\times C_n^1+C_n^2\times C_n^2+...+C_n^n\times C_n^n$$
输入格式
第一行一个整数$T$,表示数据组数。
接下来$T$行,每一行包含一个整数$n$,含义如题所示。
输出格式
输出$T$行,每行包含一个整数,表示对$10^9+7$取模后的答案。
样例
样例输入:
2
1
2
样例输出:
2
6
数据范围与提示
对于$30\%$的数据,$T\leqslant 500,n\leqslant 10,000$。
对于$100\%$的数据,$T\leqslant 100,000,n\leqslant 1,000,000$。
题解
打表找规律可以发现答案其实就是$C_{2n}^n$,那么我们现在来讲一下这到底是为什么。
先来讲个故事:
我家门前有两棵树,一棵是枣树,另一棵也是枣树。——鲁迅
我家门前有两棵枣树,一棵枣树上有$n$颗枣,另一棵枣树上也有$n$颗枣。——$HEOI-$动动
麻麻让我在这两棵枣树上摘$n$棵枣,有多少种方案数呢?
我们假设在第一棵树上摘$i$颗枣,那么另一棵树上要摘$n-i$颗枣,方案数就是:$C_n^i\times C_n^{n-i}$,那么总的方案数就是$\sum \limits_{i=0}^n C_n^i\times C_n^{n-i}$。
然而,枣是一样的,树也是一样的,那么方案数也可以写成:$C_{2n}^n$。
也就是说$C_{2n}^n=\sum \limits_{i=0}^n C_n^i\times C_n^{n-i}$。
我们还知道$C_n^i=C_n{n-i}$,于是上式就变成了:$C_{2n}^n=\sum \limits_{i=0}^n {(C_n^i)}^2$。
那么$C_n^0\times C_n^0+C_n^1\times C_n^1+C_n^2\times C_n^2+...+C_n^n\times C_n^n=C_{2n}^n$。
故事讲完啦,小朋友们都懂了嘛~
时间复杂度:$\Theta(T\times \log_{mod}n)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
int n;
long long jc[2000001],inv[2000001];
long long qpow(long long x,long long y)
{
long long res=1;
while(y)
{
if(y%2)res=res*x%mod;
y>>=1;
x=x*x%mod;
}
return res;
}
void pre_work()
{
jc[0]=1;
for(long long i=1;i<=2000000;i++)
jc[i]=jc[i-1]*i%mod;
inv[2000000]=qpow(jc[2000000],1000000005)%mod;
for(long long i=2000000;i>0;i--)
inv[i-1]=inv[i]*i%mod;
}
long long get_C(int x,int y){return jc[x]*inv[y]%mod*inv[x-y]%mod;}
int lucas(int x,int y)
{
if(!y)return 1;
return get_C(x%mod,y%mod)*lucas(x/mod,y/mod)%mod;
}
int main()
{
pre_work();
int T;scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
printf("%d\n",lucas(n<<1,n));
}
return 0;
}
rp++