AcWing——杨辉三角

下面的图形是著名的杨辉三角形:

 

如果我们按从上到下、从左到右的顺序把所有数排成一列,可以得到如下数列:

1, 1, 1, 1, 2, 1, 1, 3, 3, 1, 1, 4, 6, 4, 1, ...

给定一个正整数 N,请你输出数列中第一次出现 N 是在第几个数?

输入格式

输入一个整数 N。

输出格式

输出一个整数代表答案。

数据范围

对于 20%的评测用例,1≤N≤10;
对于所有评测用例,1≤N≤109。

输入样例:

6

输出样例:

13

题意:

求N在杨辉三角中最早出现的位置

分析:

1.分析这题我们得看斜行 

2.由于对称性且要求最早出现,那么我们答案只可能出现在对称轴的左边

3.看第二斜行可得答案一定有解

4.因为N小于1e9,且C(32,16)<1e9,C(34,17)>1e9,所以N只可能在1~16斜行

5.要求N出现的最早位置,我们应该从第16斜行开始找,为啥嘞?因为如果在越后一斜行找到,那么N所在的列数就越小,为啥嘞?因为在它是在那个位置最大的数了,其他跟它同一行以及比它小行的数都比他小。

6.怎么判断N是否在枚举的那一行里嘞?由于每一斜行都是单调递增的,因此我们可以考虑二分,设当前斜行为第k,则这一行最小为第一个的值C(k,2k),右边界为C(k,n)(一定大于等于n)。

#include 
#include 

using namespace std;
typedef long long ll;

int n; 
//计算组合数,用ll,如果>n就退出,以防爆ll
ll C(int a,int b){
	ll res=1;
	for(int i=a,j=1;j<=b;--i,++j){
		res=res*i/j;
		if(res>n){
			return res;
		}
	}
	return res;
}
bool check(int k){
	int l=2*k,r=max(n,l);//r原本等于n,但为了特判n==1的情况,因为如果n==1,l就>r,就搞不出来了
	while(l<=r){
		int mid=(l+r)/2;
		if(C(mid,k)>n){
			r=mid-1;
		}else if(C(mid,k)>n;
//从第16斜行开始找,找到就退出
	for(int i=16;;i--){
		if(check(i)){
			break;
		}
	}
	return 0;
} 












你可能感兴趣的:(蓝桥杯最后一个月冲刺,算法,c++,蓝桥杯)