3418. 杨辉三角形

题目链接

3418. 杨辉三角形

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

image

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

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

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

输入格式

输入一个整数 \(N\)

输出格式

输出一个整数代表答案。

数据范围

对于 \(20\%\) 的评测用例,\(1≤N≤10\)
对于所有评测用例,\(1≤N≤10^9\)

输入样例:

6

输出样例:

13

解题思路

二分

由于杨辉三角是左右对称的,可以将其分为两半:
image
斜着看,数值递增,可以考虑枚举每个数的开始位置,注意,这里需要逆序遍历,因为第二个斜行一定存在解,且如果逆序前面的数存在解的话一定比前面所有的解都要靠前

  • 时间复杂度:\(O(16logn)\)

代码

// Problem: 杨辉三角形
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/3421/
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

int n;
LL C(int a,int b)
{
	LL res=1;
	for(int i=1,j=a;i<=b;i++,j--)
	{
		res=res*j/i;
		if(res>n)return res;
	}
	return res;
}
bool ck(LL k)
{
	LL l=2*k,r=max(1ll*n,l);
	while(l<r)
	{
		LL mid=l+r>>1;
		if(C(mid,k)>=n)r=mid;
		else
			l=mid+1;
	}
	if(C(r,k)!=n)return false;
	cout<<r*(r+1)/2+k+1;
	return true;
}
int main()
{
    cin>>n;
    for(LL k=0;k<=16;k++)
    	if(ck(k))break;
    return 0;
}
posted @ 2022-02-20 20:38  zyy2001  阅读(262)  评论(0编辑  收藏  举报