首先看一下这道题,我以为能够找出什么规律,还小小地写了一下前几行,渴望能够找到O(1)的答案。
注意:以下所有和数组有关的都是从0开始的,0行0列是存在的!
但是我发现这很难,后来我到处找题解,发现原来杨辉三角的规律是 。
好,知道规律了,又怎么样呢?难道要一个个枚举i和j直到找到答案吗。这时很多题解都想到了及时止损,也就是说既然越往下越大,那么如果在某一斜列就已经大于1e9(给定的最大数据范围)了,那么也不必再往下一点点计算找出杨辉三角的数了。所以我们找一个值,看看在哪个位置第一次出现比1e9大的数。结果发现在。那太好了,这一位置对应的更往下的斜列肯定会更大于1e9,也就是说.
那么现在就可以分为三种情况讨论了:
1.在杨辉三角的前2001(从0到2000)行中,计算一下,把前2001行填到数组中,如果恰好找到了,那么就太好了。但是题目要求的是这个n在数列中出现的位置,我们怎么求呢?
幸好杨辉三角还有规律,就是第0行有1个数,第1行有2个数,那么第i行之前有多少个数呢?原来是:.
第i行之前有这么多个数,那么第i行第j列呢?原来是:.
好,第一种情况我们找到了。
那如果不在前2001行出现怎么办呢?那说明在之后的某一行的第1个数或者第2个数(每行的第0个数是1)。为什么这么说呢,因为第2001行的第3个数已经了,再往下走肯定还是大于1e9啊,更找不到我们想要的n了。所以我们现在就要在某一行的第1列或者第2列找到这个数。
2.某一行的第二列:.好,那么我们如何找到这个a呢,观察一下这个等式的结果:
找到a了!那么就来看看这个如果等于,太好了,找到了!
现在看看找到的话n在序列中的位置:.(注意是第2列,所以加3)。
不等于,那只好去找最后一种情况了。
3.某一行的第一列:.我们通过观察杨辉三角可以知道第a行的第1列的数不就是a本身吗。那么如果n就是第n行第1列的数,就很好求了。
从第0行到第n-1行一共多少个数:.
那么第n行第1列在数列中对应的元素个数,也就是我们要的结果就是:.
好,现在三种情况都找到了!开始写代码吧。
对了!记得对1做一个特判,不然会报错!
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<cmath>
#define ll long long
using namespace std;
int yh[2005][2005];
int main(){
ll n;
cin>>n;
memset(yh, 0, sizeof(yh));
if(n == 1){
cout<<1<<endl;
return 0;
}
yh[0][0] = 1;
for(int i = 1; i < 2001;i++){
yh[i][0] = 1;
for(int j = 1; j <= i; j++){
yh[i][j] = yh[i - 1][j - 1] + yh[i - 1][j];
if(yh[i][j] == n) {
cout<<i * (i + 1) / 2 + j + 1<<endl;
return 0;
}
}
}
// n * (n - 1) / 2 == N
ll a = sqrt(n * 2) + 1;
if(a * (a - 1) / 2 == n){
cout<<a * (a + 1) / 2 + 3<<endl;
return 0;
}else{
cout<<n * (n + 1) / 2 + 2<<endl;
return 0;
}
return 0;
}
好了,这就是这道杨辉三角题了。本菜鸡为了cv这道题找了好多题解,感谢各位大神的题解!