排列组合

题目描述
T组数据,每次给定 n,请求出下式的值,对10^9+7 取模:
C(n,0)*C(n,0)+C(n,1)*C(n,1)+C(n,2)*C(n,2)+……+C(n,n)*C(n,n)

输入格式
第一行一个整数T,表示数据组数。
接下来T行,每一行包含一个整数n,含义如题所示。

输出格式
输出T行,每行包含一个整数,表示对10^9+7取模后的答案。

样例输入
2
1
2

样例输出
2
6

数据范围与约定
对于30%的数据,T<=500 , n<=10000。
对于100%的数据,T<=100000 , n<=1000000。

题解

前30%的数据:存下阶乘以及阶乘的逆元,每次暴力做就好了。

前100%的数据:
这算是一道考察思维的题目,思路源自于一道文化课题目,原题的答案做法是暴力推式子。当时想到了这样一个比较优秀的做法,对思维具有很好的启发作用,即考虑式子的组合意义。

首先考虑,将C(n,i)*C(n,i)换成C(n,i)*C(n,n-i)。这样的话,就是对于每个 i,计算n个中选i个的方案数乘上 n个中选(n-i)个的方案数,最后累加起来。这样得到的答案,实际上相当于2n个物品, 在前 n个中选i个, 在后 n个中选(n-i)个, 又由于i取遍0~n 所有整数,
那么累加后方案数就等于C(2n,n)。
所以每次输出C(2n,n)即可,同样预处理阶乘及逆元,复杂度O(n*log+T)。

实际上这道题打表找规律说不定也能找到规律

附上代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mod=1000000007;
int T,n;
long long jc[2000005],njc[1000005],ans;
void exgcd(long long a,long long b,long long &x,long long &y)
{
    if(!b) {x=1;y=0;return;}
    exgcd(b,a%b,x,y);
    long long t=x;x=y;y=t-a/b*x;
}
long long getinv(long long a)
{
    long long x=0ll,y=0ll;
    exgcd(a,mod,x,y);
    return (x%mod+mod)%mod;
}
int main()
{
    scanf("%d",&T);
    jc[1]=1;njc[0]=1;
    for(int i=2;i<=2000000;i++) jc[i]=jc[i-1]*i%mod;
    for(int i=1;i<=1000000;i++) njc[i]=getinv(jc[i]);
    while(T--)
    {
        scanf("%d",&n);
        long long re=1ll*jc[2*n]*njc[n]%mod*njc[n]%mod;
        printf("%lld\n",re);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值