您的位置:首页 > 其它

台阶问题

2013-08-20 16:41 211 查看
有一个100个台阶的阶梯,一次可以选择上一个台阶,或者两个台阶,最后上到楼梯顶有几种走法?

很明显的递归方程:f(n)=f(n-1)+f(n-2),f(1)=1,f(2)=2.求f(100).

/*file: refibnacii.c*/
/* input one number between 1 and 100, print the output of the result */

/*
* Sample Input: 100
* Sample Output: 573147844013817084101
*/

#include <stdio.h>
#include <assert.h>
#include <string.h> /*memcpy*/
#include <stdlib.h> /*atoi*/

/* redefine N we can accept any large input */
#define N (100)

int main(int argc, char **argv){
int n,i,j;
unsigned char t
,a
,b
;
unsigned char carry,sum;

assert (2==argc);
n=atoi (argv[1]);
assert (0<n && n<101);

if (1==n){
printf ("%d\n",1);
return 0;
}

memset (a,0,N);
memset (b,0,N);
a[0]=1;
b[0]=2;

for (i=2; i<n; ++i){
memcpy (t,b,N);
carry=0;
for (j=0; j<N; j++){
sum = b[j]+a[j]+carry;
carry = sum/10;
b[j] = sum%10;
}
memcpy (a,t,N);
}

for (i=N-1; i>=0; i--){
if (b[i]){
break;
}
}
for (j=i; j>=0; j--){
printf ("%c",b[j] | 0x30);
}
printf ("\n");

return 0;
}

即使是用 __int64 来存储,也会产生溢出,所以写了如上的不会溢出的程序。下面的程序在第92个数的时候产生溢出:

#include "stdio.h"

int main(int argc, char* argv[])
{
__int64 f1 = 1, f2 = 2, tmp;

int i;

printf("%d: %I64d\n", 1, f1);
printf("%d: %I64d\n", 1, f2);

for (i=0; i<98; i++)
{
tmp = f2 ;
f2 = f1 + f2;
f1 = tmp;
printf("%d: %I64d\n", i+3, f2);
}

return 0;
}


输出为:

1: 1
1: 2
3: 3
4: 5
5: 8
6: 13
7: 21
8: 34
9: 55
10: 89
11: 144
12: 233
13: 377
14: 610
15: 987
16: 1597
17: 2584
18: 4181
19: 6765
20: 10946
21: 17711
22: 28657
23: 46368
24: 75025
25: 121393
26: 196418
27: 317811
28: 514229
29: 832040
30: 1346269
31: 2178309
32: 3524578
33: 5702887
34: 9227465
35: 14930352
36: 24157817
37: 39088169
38: 63245986
39: 102334155
40: 165580141
41: 267914296
42: 433494437
43: 701408733
44: 1134903170
45: 1836311903
46: 2971215073
47: 4807526976
48: 7778742049
49: 12586269025
50: 20365011074
51: 32951280099
52: 53316291173
53: 86267571272
54: 139583862445
55: 225851433717
56: 365435296162
57: 591286729879
58: 956722026041
59: 1548008755920
60: 2504730781961
61: 4052739537881
62: 6557470319842
63: 10610209857723
64: 17167680177565
65: 27777890035288
66: 44945570212853
67: 72723460248141
68: 117669030460994
69: 190392490709135
70: 308061521170129
71: 498454011879264
72: 806515533049393
73: 1304969544928657
74: 2111485077978050
75: 3416454622906707
76: 5527939700884757
77: 8944394323791464
78: 14472334024676221
79: 23416728348467685
80: 37889062373143906
81: 61305790721611591
82: 99194853094755497
83: 160500643816367088
84: 259695496911122585
85: 420196140727489673
86: 679891637638612258
87: 1100087778366101931
88: 1779979416004714189
89: 2880067194370816120
90: 4660046610375530309
91: 7540113804746346429
92: -6246583658587674878
93: 1293530146158671551
94: -4953053512429003327
95: -3659523366270331776
96: -8612576878699335103
97: 6174643828739884737
98: -2437933049959450366
99: 3736710778780434371
100: 1298777728820984005


注:__int8、__int16、__int32、__int64 分别是定义8位、16位、32位、64位有符号整数的关键字,其表示范围分别是-128~127、-65536~65535、-2147483648~2147483647、-9223372036854775808~9223372036854775807,其数量级分别是10^2(百)、10^4(万)、10^9(十亿)、10^18(百亿亿)。

正确结果573147844013817084101达到了10^20数量级。所以产生了溢出。

网上有一个O(logn)的时间算法。其来源于这样一个公式,设数学函数f(n)表示第n个fibonacci数,即f(1)=1, f(2)=1, f(3)=2,f(4)=3……然后求第n个fibonacci数转化为求矩阵{1,1;1,0}的n-1次方(左上角元素即为结果)。求次方可以使用折半的方法求出来。



以下是代码:

/*
* szl_fibonacci.c
*
* copyright @ dnxiaochou@gmail.com
*
* overflow at the 93th fibonacci number.
*/

/* time complexity: O(logN) */

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* a math formula is used in the following algorithm.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <stdio.h>
#include <assert.h>

typedef struct _matrix_2x2{
long long int m_00;
long long int m_01;
long long int m_10;
long long int m_11;
}Matrix_2x2;

/* init fibonacii */
void matrix_init_fibonacci (Matrix_2x2 * m_dest){
m_dest->m_00 = 1;
m_dest->m_01 = 1;
m_dest->m_10 = 1;
m_dest->m_11 = 0;
}

/* clone */
void matrix_clone (Matrix_2x2 * m_dest, const Matrix_2x2 * m_src){
m_dest->m_00 = m_src->m_00;
m_dest->m_01 = m_src->m_01;
m_dest->m_10 = m_src->m_10;
m_dest->m_11 = m_src->m_11;
}

/* matrix multiply */
void matrix_mul (Matrix_2x2 * m_dest, const Matrix_2x2 * m_src1, const Matrix_2x2 * m_src2){
m_dest->m_00 = m_src1->m_00 * m_src2->m_00 + m_src1->m_01 * m_src2->m_10;
m_dest->m_01 = m_src1->m_00 * m_src2->m_01 + m_src1->m_01 * m_src2->m_11;
m_dest->m_10 = m_src1->m_10 * m_src2->m_00 + m_src1->m_11 * m_src2->m_10;
m_dest->m_11 = m_src1->m_10 * m_src2->m_01 + m_src1->m_11 * m_src2->m_11;
}

/* get power of a matrix */
void matrix_power (Matrix_2x2 * m_dest, const Matrix_2x2 * m_src, int n){
Matrix_2x2 m_tmp;

assert (0 < n);

if (1 == n){
matrix_clone (m_dest, m_src);
}
else if (1 & n){
matrix_power (&m_tmp, m_src, (n-1)>>1);
matrix_mul (m_dest, &m_tmp, &m_tmp);
matrix_mul (&m_tmp, m_dest, m_src);
matrix_clone (m_dest, &m_tmp);
}
else{
matrix_power (&m_tmp, m_src, n>>1);
matrix_mul (m_dest, &m_tmp, &m_tmp);
}
}

long long int fibonacci (int n){
long long int ret = 1;
Matrix_2x2 mat_fib_1, mat_fib_dec_n;

matrix_init_fibonacci (&mat_fib_1);
matrix_clone (&mat_fib_dec_n, &mat_fib_1);

if (1 < n){
matrix_power (&mat_fib_dec_n, &mat_fib_1, n-1);
}
return mat_fib_dec_n.m_00;
}

int main (int argc, char * * argv){
int n,i;
long long int f;
scanf ("%d", &n);
for (i=1; i<n; i++){
f = fibonacci (i);
printf ("%d\t%lld\n", i, f);
}

return 0;
}


不过因为是long long int 类型,所以还是在第93个溢出了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: