Train into the stack problem (how to quickly calculate the number of single combinations)

topic

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

Guess you like

Origin blog.csdn.net/zhangjianjunab/article/details/107831039