3418. 杨辉三角形
题目链接
3418. 杨辉三角形
下面的图形是著名的杨辉三角形:
如果我们按从上到下、从左到右的顺序把所有数排成一列,可以得到如下数列:
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
解题思路
二分
由于杨辉三角是左右对称的,可以将其分为两半:
斜着看,数值递增,可以考虑枚举每个数的开始位置,注意,这里需要逆序遍历,因为第二个斜行一定存在解,且如果逆序前面的数存在解的话一定比前面所有的解都要靠前
- 时间复杂度:\(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;
}