典型的卡特兰数应用题,直接求组合数C(2n,n)-C(2n,n-1)即可,但是要注意,由于这道题n的范围是n<=100,很容易爆longlong,如果是用c++写的话需要写压位高精度,但是如果用java的话就可以直接调用大数类就行,c++快很多,而且只要改一下N,当n达到60000的时候也能轻松过,但是Java直接写的话n大一点会tle,不过对于这题的数据还是能过的
c++版本ac 31ms:
#include<cstdio>
#include<cstring>
typedef long long ll;
const int N=250;
const int bit=1e9;//压9位
int cnt,tt;
ll primes[N],powers[N],res[N];
bool vis[N];
//用来获取n!中p的个数
int get(int n,int p)
{
int s=0;
while(n){
s+=n/p;
n/=p;
}
return s;
}
//线筛
void get_primes(int n)
{
for(int i=2;i<=n;i++){
if(!vis[i])primes[cnt++]=i;
for(int j=0;primes[j]<=n/i;j++){
vis[i*primes[j]]=true;
if(i%primes[j]==0)break;
}
}
}
//等价于约分
void get_red(int n)
{
for(int i=0;i<cnt;i++){
int p=primes[i];
powers[p]=get(2*n,p)-get(n,p)*2;
}
int k=n+1;
for(int i=2;i<=k;i++){
while(k%i==0){
powers[i]--;
k/=i;
}
}
}
void mul(int b)
{
int t=0;
for(int i=0;i<=tt;i++){
res[i]=res[i]*b+t;
t=res[i]/bit;
res[i]%=bit;
}
while(t){
res[++tt]=t%bit;
t/=bit;
}
}
void print()
{
printf("%lld",res[tt]);
for(int i=tt-1;i>=0;i--)printf("%09lld",res[i]);
printf("\n");
}
int main()
{
int n;
get_primes(210);
while(~scanf("%d",&n))
{
memset(res,0,sizeof(res));
memset(powers,0,sizeof(powers));
get_red(n);
res[0]=1;
for(int i=2;i<=2*n;i++){
while(powers[i]--)mul(i);
}
print();
}
return 0;
}
java版本ac 327ms:
import java.util.*;
import java.lang.*;
import java.math.*;
public class Main{
public static void main(String[] args){
Scanner in=new Scanner(System.in);
while(in.hasNext()){
int n=in.nextInt();
BigInteger res=BigInteger.valueOf(1);
for(int i=1,j=2*n;i<=n;i++,j--){
res=res.multiply(BigInteger.valueOf(j));
res=res.divide(BigInteger.valueOf(i));
}
BigInteger ans=BigInteger.valueOf(1);
for(int i=1,j=2*n;i<=n-1;i++,j--){
ans=ans.multiply(BigInteger.valueOf(j));
ans=ans.divide(BigInteger.valueOf(i));
}
res=res.subtract(ans);
System.out.println(res);
}
}
}
ps:如果题目改一下,只要求输出取模后的结果,且mod p p为素数,那么可以结合Lucas定理来求