HDU5620 KK's Steel【菲波拉契数列+水题】

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(1N1018) 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(1T10), which indicates the number of test cases.

Each test case contains one line including a integer N(1N1018),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;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值