zoukankan      html  css  js  c++  java
  • 火车进栈问题(如何快速计算单个组合数)

    题目

    题目

    思路

    这道题目思路不难,就是卡塔兰数,但是关键是要压位高精,而且如何快速计算组合数,这里把公式说一下:(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;
    }
    
  • 相关阅读:
    动词 + to do、动词 + doing
    图像直线检测——霍夫线变换
    x=min(x, y)
    x=min(x, y)
    算法 Tricks(三)—— 数组(序列)任意区间最小(大)值
    算法 Tricks(三)—— 数组(序列)任意区间最小(大)值
    分治法求解切割篱笆
    分治法求解切割篱笆
    GMM的EM算法实现
    秒杀多线程第二篇 多线程第一次亲热接触 CreateThread与_beginthreadex本质差别
  • 原文地址:https://www.cnblogs.com/zhangjianjunab/p/13444231.html
Copyright © 2011-2022 走看看