(a/b)%mod = (a%mod*(b的逆元))%mod
逆元求法:
//1: 通用扩展欧几里得;
long long extend_gcd(long long a,long long b,long long &x,long long &y)
{
if(a==0&&b==0) return -1;//无最大公约数
if(b==0){x=1;y=0;return a;}
long long d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
//*********求逆元素*******************
//ax = 1(mod n)
long long mod_reverse(long long a,long long n)
{
long long x,y;
long long d=extend_gcd(a,n,x,y);
if(d==1) return (x%n+n)%n;
else return -1;
}
//2.mod 为质数特殊情况
//第一种 递推 inv[i] = inv[mod%i]*(mod-mod/i)%mod;
//第二种 费马小定理a^(mod-1)%mod = 1 a关于m的逆元a^mod-2;
卡特兰数 h(n) = c(n,2n)/(n+1) = (4*n-2)*h(n-1)/(n+1);
当遇到组合数和序号匹配或出栈次序相似的问题往这方面想
#include<cstdio>
#define mod 1000000007
#define LL long long
LL t,cat[500005],n,ans,c[1000005],inv[1000005];
void init()
{
cat[0] = 1;
inv[1] = 1;
for (int i = 2; i <= 1000000; i++)
inv[i] = inv[mod%i]*(mod-mod/i)%mod;
for(LL i=1;i<=500005;i++)
cat[i] = (cat[i-1]*(4*i-2))%mod*inv[i+1]%mod;
}
void gao()
{
c[0] = 1;
for(LL i=1;i<=n;i++)
c[i] = (c[i-1]*(n-i+1))%mod*inv[i]%mod;
}
int main()
{
init();
scanf("%I64d",&t);
while(t--)
{
scanf("%I64d",&n);
gao();
ans = 0;
for(LL i=0;i*2<=n;i++)
ans = (ans+c[i*2]*cat[i])%mod;
printf("%I64d\n",ans);
}
return 0;
}