0
点赞
收藏
分享

微信扫一扫

杨辉三角蓝桥杯第十二届省赛题(纯C语言版)

小猪肥 2022-04-16 阅读 40

刚开始是用了数组存储查找,会超时,只能通过30%的案例;

然后看了CSDN两位大佬的思路和解法(二项式是真的六啊,,,):

第十二届蓝桥杯B组C/C++省赛—H题(杨辉三角)_思维题_萌小帝的博客-CSDN博客

求杨辉三角中元素首次出现位置【2021蓝桥杯】_LMoon琉月的博客-CSDN博客_杨辉三角形某个数第一次出现

(但是用纯C语言去写还是会超时,所以自己做了一些修改) 

关于二项式的思路,两位大佬的文里面都有详细的讲解,我这里就不再班门弄斧。

直接上代码,关于修改的地方和需要注意的地方代码中有注释。

#include<stdio.h>
long long g[20]={0};//用于存储阶乘分母 
long long mymax(long long a,long long b)//两值中找最大值; 
{
	if(a>=b)
		return a;
	else
		return b;
}

long long binomial(int a,int k,long long n)/*(a,k分别是C(n,k)里面的n和k;)这里使用二项式计算杨辉三角中的值,但是定义了一个n,因为二项式的计算是(n*(n-1)*(n-2)*...*(n-k))/k!
 用g[k]存储了k!,然后在下面的循环中计算1/g[k] *a*(a-1),一旦乘积大于了n,就没有继续计算下去的必要了,直接跳出,这样就能减小运算时间。*/
{
	int i;
	long long f=1,gg=1;
	if(g[k]==0)
	{
		for(i=1;i<=k;i++)
		{
			gg=gg*i;//分母 
		}
		g[k]=gg;
	}
	for(i=0;i<k;i++)
	{
		f=f*(a-i);
		
		if(f/g[k]>n)
		{
			break;
		}
		
	
	}
	return f/g[k];
}

int localmax(long long n)/*这里计算出到第几斜行的第一个元素是大于n值的,那第一个n值出现的位置一定是在该斜行的左边*/ 
{
	int k;
	for(k=1;k<=100;k++)
	{
		if(binomial(2*k,k,n)>n)
		{
			break;
		}
	}
	return k;
}
long long erf(int k,int min,long long n)/*二分查找,减小时间复杂度*/ 
{
	int l=min;
	long long r=mymax(l,n);
	while(l<r)
	{
		long long mid=(l+r)/2;
		if(binomial(mid,k,n)>=n)
		{
			r=mid;
		}
		else
		{
			l=mid+1;
		}
	}
	if(binomial(r,k,n)!=n)
		return 0;
	else
		return r;/*返回所在行-1的数*/ 
}
int main()
{
	int maxk,i,a,k;
	long long n;
	scanf("%lld",&n);
	if(n==1)
	{
		printf("1");
		return 0;
	}
	maxk=localmax(n);
	for(i=maxk-1;i>0;i--)
	{
		if(erf(i,2*i,n))
		{
			k=i;
			a=erf(i,2*i,n)+1;
			break;
		}
	}
	
	long long order=0;
	for(i=1;i<a;i++)
		order=order+i;
	order=order+k+1;
	printf("%d %d\n",k,a);//这里为了方便理解所以输出了斜行数和层数,测试时记得注释掉 
	printf("%lld",order);
	return 0;
}

 

举报

相关推荐

0 条评论