PREV-284 杨辉三角形

 

解题思路一 缩小查找范围法

1.首先将三角形转换为如下形式:

2.观察规律:

设行数为a,列数为b,f(a,b)为每个位置上的值

则f(a,1)=1,f(a,2)=a-1,f(a,3)=(1+a-2)(a-2)/2=(a-1)(a-2)/2

3.进行分析:

评测用例给出的最大值为1000000000(10亿)

将其带入f(a,3)可得a=44722.86

即f(44722,3)<10亿,f(44723,3)>10亿

又可以看到当a>4时,f(a,3)>f(a,2)

所有我们在进行搜索时,只需要搜索到44722行即可

超过f(44722,3)的数字必定在第2列,因此可以通过f(a,2)表达式计算它所在的行数

4.实现代码:

# include <stdio.h>
typedef long long LL;
LL N[44722];
LL num;
bool check(LL n,int i,int j)
{
	if(n==num)
	{
		printf("%I64d",(LL)((i-1)*i/2+j));
		return true;
	}
	else return false;
}
int main()
{
	scanf("%I64d",&num);
	N[1]=1;
	if(num==1)
	{
		printf("1");
		return 0;
	}
	for(int i=2;i<=44722;++i)
	{
		if(i%2==0)
		{
			for(int j=i/2;j>1;--j)
			{
				N[j]+=N[j-1];
				if(check(N[j],i,j))return 0;
			}
		}
		else
		{
			for(int j=i/2+1;j>1;--j)
			{
				if(j==i/2+1)N[j]=2*N[j-1];        
				else N[j]+=N[j-1];
				if(check(N[j],i,j))return 0;
			}
		}
	}
	printf("%I64d",(LL)((num+1)*num/2+2));
	return 0;
}

解题思路二 斜行查找法

1.首先将三角形转换为如下形式:

其中每一列相当于原三角形的一斜行

2.观察规律:

设行数为a,列数为b,f(a,b)为每个位置上的值,查找的数字为n

当a>=2b-1时,f(a,b)>{x<=a,y<b|f(x,y)},且f(a,b)=C(a-1,b-1)

当b>1时,f(a+1,b)>f(a,b)

当a<=b/2时(四舍五入),f(a,b+1)>f(a,b)

3.进行分析:

因为第二列为首项为1公差为1的等差数列,所以f(n+1,2)=n,也就是说n必然出现在第2列第n+1行。又因为每一列新出现的值是从2b-1行开始的,所以我们每一列查找的范围应该是从第2b-1行到第n行,即{a|2b-1<=a<=n}。

评测用例给出的最大值为1,000,0。00,000(10亿)。当b=14时,f(2b-1,b)=6,227,020,800。当b=13时,f(2b-1,b)=479,001,600。所以我们只需检查第13列到第3列。

因为每列从上往下单调递增,所以我们可以用二分法检查每一列。

3.实现代码:

# include <stdio.h>
typedef long long LL;
LL num;
LL cbn(LL x,LL y)
{
	LL ans=1;
	for(LL i=x-y+1,j=1;j<=y;++i,++j)
	{
		ans=ans*i/j;
		if(ans>num)break;
	}
	return ans;
}
bool check(LL col)
{
	LL L=2*col-2;
	LL R=num-1;
	while(L<=R)
	{
		LL mid=L+(R-L)/2;
		if(cbn(mid,col-1)>num)R=mid-1;
		else if(cbn(mid,col-1)<num)L=mid+1;
		else
		{
			printf("%I64d",((1+mid)*mid/2+col));
			return true;
		}
	}
	return false;
}
int main()
{
	scanf("%I64d",&num);
	if(num==1)
	{
		printf("1");
		return 0;
	}
	for(int i=13;i>=3;--i)
	{
		if(check(i))return 0;
	}
	printf("%I64d",((1+num)*num/2+2));
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值