topic
Ideas
The idea of this topic is not difficult, it is the Catalan number, but the key is to suppress the position and high precision, and how to quickly calculate the combined number, here is the formula: C 2 nnn + 1 \frac{C_{2n}^{n }}{n+1}n+1C2 nn。
That is: (2 n)! N! ∗ n! ∗ (n + 1) \frac{(2n)!}{n!*n!*(n+1)}n!∗n!∗(n+1)( 2 N ) !, The faster way is to decompose the factorial with the method https://www.acwing.com/problem/content/199/, then subtract the exponent, and then quickly exponentiate it back, but why fast exponentiation? Isn't this high precision multiplied by high precision? Isn't it good for us to multiply high precision by single precision?
But according to what the big guy said and his own feeling, the fast power is higher than a single single multiplication.
Then you can get stuck.
Code
The time complexity should be: O (n 2) O(n^2)O ( n2 )Yes, I don't know (how to calculate the time complexity of this magical method QAQ), but it can be passed because the constant is small and the running is not satisfied.
#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("\n");
return 0;
}