KK's Steel
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1201 Accepted Submission(s): 585
Problem Description
Our lovely KK has a difficult mathematical problem:he has a
N(1≤N≤1018) meters steel,he will cut it into steels as many as possible,and he doesn't want any two of them be the same length or any three of them can form a triangle.
Input
The first line of the input file contains an integer
T(1≤T≤10), which indicates the number of test cases.
Each test case contains one line including a integer N(1≤N≤1018),indicating the length of the steel.
Each test case contains one line including a integer N(1≤N≤1018),indicating the length of the steel.
Output
For each test case, output one line, an integer represent the maxiumum number of steels he can cut it into.
Sample Input
1 6
Sample Output
3
Hint
1+2+3=6 but 1+2=3 They are all different and cannot make a triangle.
Source
问题链接:HDU5620 KK's Steel。
问题描述:参见上文。
问题分析:
刚读到题,有点难解,没有头绪。
看了暗示才明白点,有点像菲波拉契数列,不过每一项求的是数列到该项之和。另外略有不同的是,第1项是1,第2项是2。也许是为了三个钢管围起来不能成为三角形的原因。
既然知道以上这些,那就先打表备查,这是为了节省计算时间,尽管有时候是多余的,但是多数程序都需要打表,那就打表吧。
需要说明的一点是,菲波拉契序列的各项值增长是极快的,其和的增长就更快了,不用95项就达到了所需要的值的范围。这个项数计算,作为定义数组大小的依据,不能随便来的,需要事先做点功课的。
这里给出两个版本,C++语言版采用顺序查找;C语言版本采用二分查找(速度快一些)。
程序说明:(略)
AC的C语言程序如下:
#include <stdio.h>
#define MAXN 95
unsigned long long fsum[MAXN+1];
/* 递推法:计算斐波拉契数列的第1到n项之和 */
/* 这里略有不同,第2项是2,其他基本相同 */
void fibsum(unsigned long long fsum[], int n)
{
fsum[0] = 0;
fsum[1] = 1;
fsum[2] = 3;
if(n <= 2)
return;
unsigned long long f1 = 1, f2 = 2, temp;
int i;
for(i=3; i<=n; i++) {
temp = f1 + f2;
f1 = f2;
f2 = temp;
fsum[i] = fsum[i-1] + temp;
}
}
int main(void)
{
// 计算斐波拉契数列的第1到n项之和,打表
fibsum(fsum, MAXN);
int t, start, mid, end;
unsigned long long n;
scanf("%d",&t);
while(t--) {
scanf("%llu",&n);
// 二分查找
start = 0;
end = MAXN;
for(;;) {
if(start > end)
break;
mid = (start + end) / 2;
if(fsum[mid] < n)
start = mid + 1;
else if(fsum[mid] > n)
end = mid - 1;
else if(fsum[mid] == n)
break;
}
if(n < fsum[mid])
mid--;
printf("%llu\n", mid);
}
return 0;
}
AC的C++语言程序如下:
/* HDU5620 KK's Steel */
#include <iostream>
using namespace std;
const int MAXN = 100;
unsigned long long fsum[MAXN];
/* 递推法:计算斐波拉契数列的第1到n项之和 */
/* 这里略有不同,第2项是2,其他基本相同 */
void fibsum(unsigned long long fsum[], int n)
{
fsum[0] = 0;
fsum[1] = 1;
fsum[2] = 3;
if(n <= 2)
return;
unsigned long long f1 = 1, f2 = 2, temp;
int i;
for(i=3; i<n; i++) {
temp = f1 + f2;
f1 = f2;
f2 = temp;
fsum[i] = fsum[i-1] + temp;
}
}
int main()
{
// 计算斐波拉契数列的第1到n项之和,打表
fibsum(fsum, MAXN);
int t;
long long n;
cin >> t;
while(t--) {
cin >> n;
for(int i=1; i<MAXN; i++)
if(n < fsum[i]) {
cout << i-1 << endl;
break;
}
}
return 0;
}