tema
Ideas
La idea de este tema no es difícil, es el número catalán, pero la clave es suprimir la posición y alta precisión, y cómo calcular rápidamente el número combinado, aquí está la fórmula: C 2 nnn + 1 \ frac {C_ {2n} ^ {n }} {n + 1}n + 1C2 nn。
Es decir: (2 n)! N! ∗ n! ∗ (n + 1) \ frac {(2n)!} {N! * N! * (N + 1)}n ! ∗ n ! ∗ ( n + 1 )( 2 N ) !, La forma más rápida es descomponer el factorial con el método https://www.acwing.com/problem/content/199/, luego restar el exponente y luego exponenciarlo rápidamente, pero ¿por qué exponenciación rápida? ¿No es esta alta precisión multiplicada por alta precisión? ¿No es bueno para nosotros multiplicar alta precisión por precisión simple?
Pero de acuerdo con lo que dijo el grandullón y su propio sentimiento, la potencia rápida es mayor que una sola multiplicación.
Entonces puedes quedarte atascado.
Código
La complejidad del tiempo debe ser: O (n 2) O (n ^ 2)O ( n2 )Sí, no sé (cómo calcular la complejidad temporal de este método mágico QAQ), pero se puede pasar porque la constante es pequeña y la ejecución no se satisface.
#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;
}