这个题我去年比赛的时候用的就是最笨的方法,开一个二位数组,然后逐个判断。
1、这个题我们到手先分析一波,这个数据范围是小于10的9次方,时间限制是1秒,杨辉三角有一个特性是每个数字都等于肩上两个数字之和,开个10亿*10亿的二位数组不可能,而且1秒最多操作1亿次,所以这个题目不能枚举,另有技巧。
2、我们可以通过杨辉三角判断一下我们需要枚举的行数范围,第n+1行第一个数字一定是1,第二个数字是n,第三个数字n*(n-1)/2,也就是说每一个数字n一定可以从第n+1行的第二个数字里找到他的位置,但不一定是杨辉三角里第一次出现,从第二列可以保证我们要找的数字n一定能在前n+1行内找到,但是枚举前n+1行肯定会超时,我们观察第三列,判断n*(n-1)/2>=10^9,粗略计算n>=44800,如果行数超过44800,那么该行的第三个数字肯定超过10亿,而且改行第四个数字、第五个数字…直到该行的一半数字都大于10亿(杨辉三角的每行都是对称的),都不是我们判断的数字范围,也无需我们再枚举,也就说我们需要枚举的行数只需要到44800行,如果在这44800行里没有找到n,那么n就默认在n+1行的第二个数字的位置。
3、没必要开个44800*44800的二位数组,我在这里用的是两行数组来回代替去更新。也可以用一行滚动数组去更新,但两行也没问题。再一个就是关注一下第i行第j列的数字的排列数的规律,还有就是要注意有的数字要开成long long更保险。
代码如下:
#include<bits/stdc++.h>
using namespace std;
long long dp[2][44900];
int main()
{
long long n;
cin>>n;
if(n==1){
cout<<1<<endl;
return 0;
}
dp[0][1]=1;
int now=1;//now指向当前行
int last=0;//last指向上一行
long long sum=0;//数字的排列位
for(int i=2;i<=44800;i++){
for(int j=1;j<=i;j++){
dp[now][j]=dp[last][j]+dp[last][j-1];
if(dp[now][j]==n){
//cout<<i<<" "<<j<<endl;
sum=(i-1)*i/2+j;
cout<<sum<<endl;
return 0;
}
}
now=(now+1)%2;//更新一下
last=(last+1)%2;
}
sum=(n+1)*n/2+2;
cout<<sum<<endl;
return 0;
}