杨辉三角形【第十二届蓝桥杯】
资源限制
时间限制:1.0s 内存限制:256.0MB
思路一
先用数组模拟出杨辉三角形,所找的n只有两种情况,要么是在前面的某一行,要么是在n+1行的第二个数。先枚举每一行中最中间的数(也就是每一行中最大的数)直到大于n跳出,然后在这一行用二分查找(第一个数到最中间的数),能找到就返回下标,加上前面的行数,否则就另外一种情况。
#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long LL;
const int maxn = 105;
LL a[105][1005],x;
int F_x(LL dot){
LL i = 1, j = (dot+1)/2;
while(i <= j){
int mid = (i+j)/2;
if(a[dot][mid] == x){
return mid;
} else if (a[dot][mid] > x){
j = mid -1;
} else {
i = mid +1;
}
}
return 0;
}
int main(){
cin >> x;
for(LL i = 1; i <= maxn; i++){
a[i][1] = a[i][i] = 1;
}
for(LL i = 3; i <= maxn; i++){
for(LL j = 1; j < maxn; j++){
a[i][j] = a[i-1][j-1] + a[i-1][j];
}
}
int dot;
for(LL i = 1; i <= maxn; i++){ //确定到某一行
if(x <= a[i][(i+1)/2]){
dot = i;
break;
}
}
LL sum, t = F_x(dot); //判断二分查找能否在那一行找到
if(!t){
sum = (x*(x+1))/2 + 2;
} else {
sum = ((dot-1)*dot)/2 + t;
}
cout << sum << endl;
return 0;
}
这种情况只能得到80分,不知道哪种情况没考虑到
思路二
用组合法从最底部按斜行进行二分查找,这个测试用例全部通过
#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long LL;
int n;
LL c(int a, int b){ //暴力求组合数
LL res = 1;
for(int i=a,j=1; j<=b; i--,j++){
res = res*i/j;
if(res > n) return res;
}
return res;
}
bool check(int k){ //二分查找
LL l = k*2, r = n;
while(l < r){
LL mid = l+r >> 1;
if(c(mid, k) >= n) r = mid;
else l = mid+1;
}
if(c(r, k) != n) return false;
cout << r*(r+1)/2 + k + 1 << endl;
return true;
}
int main(){
cin >> n;
if(n == 1) cout << "1" << endl;
else {
for(int i = 16; ;i--){ //从底部枚举每一斜列(只看左半部分),进行二分查找
if(check(i)) break;
}
}
return 0;
}