下面的图形是著名的杨辉三角形:
如果我们按从上到下、从左到右的顺序把所有数排成一列,可以得到如下数列:
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; }