题目
题意: 杨辉三角。输入n,求在杨辉三角中第一次出现这个数是在第几个位置。(n <= 1e9)
思路: 找规律+二分。
y总说要斜着看,而且要只看一半,因为左右对称。
这样会发现每个斜行都是Cn k, n >= 2k.
C2k k >= 1e9的就不用考虑了,超出数据范围了。所以只需要看前16个斜行。
从最后一个斜行开始二分查找即可。(因为不同斜行在同一行的值是递增的,所以最后一个斜行找到的n左边的数都<n,n是第一次出现的)
时间复杂度: O(能过),1632log(n).
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#define mem(a,x) memset(a,x,sizeof(a))
#define fir(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
ll n,m,k,T;
ll C(int n,int m)
{
ll res = 1;
for(int i=n,j=1;j<=m;--i,++j)
{
res = res * i;
res = res / j;
if(res > 2e9) return res;
}
return res;
}
bool check(int k)
{
int l = 2*k,r = n;
while(l < r)
{
int mid = l+r>>1;
if(C(mid,k)>=n) r = mid;
else l = mid+1;
}
if(C(l,k)==n)
{
int dx = l - 2*k;
int m = dx + 2*k+1;
ll ans = 1ll*m*(m-1)/2;
ans += k+1;
cout<<ans;
return 1;
}
return 0;
}
void solve()
{
cin>>n;
if(n==1)
{
cout<<1;
return ;
}
for(int k=16;;--k)
{
if(check(k)) return ;
}
}
int main(void)
{
solve();
return 0;
}
/*
20007
200150030
*/