Entrene en el problema de la pila (cómo calcular rápidamente el número de una sola combinación)

tema

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;
}

Supongo que te gusta

Origin blog.csdn.net/zhangjianjunab/article/details/107831039
Recomendado
Clasificación