下面的图形是著名的杨辉三角形:
如果我们按从上到下、从左到右的顺序把所有数排成一列,可以得到如下数列:
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
杨辉三角的一些性质:左右对称,所以只要在杨辉三角右半边出现过的数都会在左半边出现过,且位置是对称的,所以答案一定是在左半边,还有就是对于每一斜行和竖行从上至下是依次增大的,需要明确的一点是所有的数都会在杨辉三角中出现,比如x,一定会有C(x,1)对应于x,所以不用担心有无解的情况,但是我们需要找到数值为x的最靠上的位置就需要从下往上枚举,因为如果x第一次出现在(i,j)这个位置,那么这个位置左上和上方以及右上的数都会比x要小,所以我们可以枚举斜行,利用二分来枚举在每一斜行中出现的位置即可,注意是从下往上枚举:
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
ll C(ll a,ll b)//求组合数
{
ll ans=1;
for(int i=a,j=1;j<=b;i--,j++)
ans*=i,ans/=j;
return ans;
}
ll n;
bool check(int k)//枚举第k斜行
{
ll l=2*k,r=max(l,n);
while(l<r)
{
ll mid=l+r>>1;
if(C(mid,k)>=n) r=mid;
else l=mid+1;
}
if(C(l,k)==n)
{
printf("%lld",l*(l+1)/2+k+1);//注意组合数是从C(0,0)开始的
return true;
}
return false;
}
int main()
{
cin>>n;
for(int i=16;;i--)//枚举斜行
if(check(i)) break;
return 0;
}