题目
思路
这道题目思路不难,就是卡塔兰数,但是关键是要压位高精,而且如何快速计算组合数,这里把公式说一下:(frac{C_{2n}^{n}}{n+1})。
也就是:(frac{(2n)!}{n!*n!*(n+1)}),较快的方法就是用https://www.acwing.com/problem/content/199/的方法分解阶乘,然后减去指数,再快速幂回来,但是为什么要快速幂呢?这不是高精度乘高精度吗,我们一位一位单精度乘高精度他不香吗。
但是据大佬所说以及自己感觉,快速幂是比单个单个乘要高的。
然后就可以卡过去了。
代码
时间复杂度应该是:(O(n^2))的吧,我不知道(这个神奇做法的时间复杂度怎么算啊QAQ),但是可以过,因为常数小,跑不满。
#include<cstdio>
#include<cstring>
#define N 121000
using namespace std;
typedef long long LL;
LL fre=10000000;int res=7;
struct node
{
LL a[6100];int len;
}an;
node operator*(node x,node y)
{
node c;memset(c.a,0,sizeof(c.a));c.len=x.len+y.len-1;
for(int i=1;i<=x.len;i++)
{
for(int j=1;j<=y.len;j++)c.a[i+j-1]+=x.a[i]*y.a[j];
}
for(int i=1;i<=c.len;i++)
{
c.a[i+1]+=c.a[i]/fre;
c.a[i]%=fre;
}
while(c.a[c.len+1])
{
c.len++;
c.a[c.len+1]+=c.a[c.len]/fre;
c.a[c.len]%=fre;
}
return c;
}
node ksm(int xx,int y)
{
node x;memset(x.a,0,sizeof(x.a));x.len=1;x.a[1]=xx;
node ans;memset(ans.a,0,sizeof(ans.a));ans.len=ans.a[1]=1;
while(y)
{
if(y&1)ans=ans*x;
x=x*x;y>>=1;
}
return ans;
}
int n,a[N],b[N],m;
bool v[N];
int solve(int x,int y)
{
int ans=0,now=y;
while(now)ans+=now/x,now=now/x;
return ans;
}
int main()
{
scanf("%d",&n);
int now=n+1,ed=2*n;
for(int i=2;i<=ed;i++)
{
if(!v[i])
{
a[++m]=i;
b[m]=solve(i,2*n)-2*solve(i,n);
while(now%i==0 && now)b[m]--,now/=i;
}
for(int j=1;j<=m && i*a[j]<=ed;j++)
{
v[i*a[j]]=1;
if(i%a[j]==0)break;
}
}
an.a[1]=an.len=1;
for(int i=1;i<=m;i++)an=an*ksm(a[i],b[i]);
printf("%lld",an.a[an.len]);
for(int i=an.len-1;i>=1;i--)
{
LL now=fre/10;
while(!(an.a[i]/now) && now>=10)//处理前缀0
{
printf("0");
now/=10;
}
printf("%lld",an.a[i]);
}
printf("
");
return 0;
}