问题链接:HDU5620
刚读到题,有点难解,没有头绪。
看了暗示才明白点,有点像菲波拉契数列,不过每一项求的是数列到该项之和。另外略有不同的是,第1项是1,第2项是2。也许是为了三个钢管围起来不能成为三角形的原因。
既然知道以上这些,那就先打表备查,这是为了节省计算时间,尽管有时候是多余的,但是多数程序都需要打表,那就打表吧。
查找的时候,可以用顺序查找的,只是略费点时间。这里采用二分查找,逻辑就稍微有点麻烦了,因为这不是找相等的数,是找一个小于或等于的数,所以要注意在二分查找之后加以调整。参见:HDU5620 KK‘s Steel(C++语言版)。
需要说明的一点是,菲波拉契序列的各项值增长是极快的,其和的增长就更快了,不用95项就达到了所需要的值的范围。这个项数计算,作为定义数组大小的依据,不能随便来的,需要事先做点功课的。
程序如下:
#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; }
HDU5620 KK's Steel(C语言版)
时间: 2024-10-12 06:41:42