斐波那契数列 Library

http://acm.tju.edu.cn/toj/showp3267.html
3267.   Library
Time Limit: 1.0 Seconds   Memory Limit: 65536K
Total Runs: 214   Accepted Runs: 96



Description

As we all know, there are very long stairs before our library in campus III of our school. It is so tired for us to go up stairs. Alpc60 has to go up and down stairs every day, what a boring walk!

One day when alpc60 went up stairs, he thought that every time he can step over one or two stairs, if there are n stairs, then how many ways he can reach the top?

The clever ACMers, can you help alpc60 to calculate how many ways he can go up n (1 ≤ n ≤ 1,000,000,000) stairs.

Because the number of the answer will be so large, you must output the number module by 9901.

Input

Each line of the input contains a number n indicating the stairs number.

Input is ended with -1 which is not the stairs number.

Output

For each case of the input output the possible ways module by 9901.

Sample Input

1
2
5
-1

Sample Output

1
2
8
Hint: The Bruce force method will simply lead to the Time Limit Exceeded error, try some efficient method to solve this problem.



Source: NUDT Programming Contest 2009

 

题意 : 上楼梯, 每次都可以上1节或2节,求有几种上楼方式,是一个典型的斐波那契数列,某状态可以是从两种情况来的,1,上两节到这儿,2,上1节到这儿,就是f[n] = f[n-1]+f[n-2]

但是因为数会很大所以要用到矩阵,和快速矩阵幂

  1 /*
  2   快速幂矩阵法
  3   dp 动态规划
  4   a[n] = a[n-1]+ a[n-2];  这是一个典型的斐波那契数列  一般斐波那契数列算到20的时候已经很大了所以一般来说要用快速法 
  5   构造矩阵有
  6   a[n-1] = q[n-1];  为了构造一个矩阵 
  7   上下两式分析有  [ a[n]   ] = [1,1]*[a[n-1]]
  8                 [ a[n-1] ] = [1,0] [a[n-2]]
  9   其中要自定义矩阵的乘法 
 10   然后递推得  转化成求矩阵幂的问题
 11 */
 12    
 13 #include<cstdio>
 14 #include<cmath>
 15 #define N 9901 
 16 using namespace std;
 17 struct mtx{
 18 //    int n;// 矩阵的阶数
 19     int a[2][2];
 20     mtx operator * (const mtx o) const {
 21         mtx c;
 22 //        return c.n = n ;
 23     c.a[0][0]= c.a[0][1] = c.a[1][0] = c.a[1][1] = 0;//做乘法前初始化 
 24         for(int i = 0 ; i < 2 ; i++ )
 25         {
 26             for(int j = 0 ; j < 2 ; j++)
 27             {
 28                 for(int k = 0 ; k < 2 ; k++)
 29                 {
 30                     c.a[i][j] += ((a[i][k]%N)*(o.a[k][j]%N))%N;
 31                     c.a[i][j] %= N;
 32                 }
 33             }
 34         }
 35         return c;
 36     } 
 37 };//定义矩阵乘法
 38 /*  如果 递归的写数幂是  
 39 int f(int a ,int b)
 40 {
 41     int ret = 1;
 42     if (b == 1 ) return a;
 43     int t = f(a,b/2)
 44     t = t*t;
 45     if(b&1)  return t*a;
 46     return  t;
 47 }
 48 
 49 但是矩阵的乘法一般不写递归形式,因为递归用栈来存储,会爆内存 
 50 
 51 非递归形式写数幂 
 52 
 53 int f (int a , int b) 
 54 {
 55     int ret = 1;
 56     while(b > 0) 
 57     {
 58         if(b&1) ret *= a;
 59         a *= a;    
 60         b >>= 1;
 61     }
 62     return ret;
 63 } 
 64 int f(int a ,int b )
 65 {
 66     int ret;
 67     for( ret = 1 ; b ; b>>=1)
 68     {
 69         if(b&1) ret*=a;
 70         a = a * a; 
 71     }
 72     return ret;
 73 }
 74 
 75 int f (int a , int b)
 76 {
 77     int ret ;
 78     for(ret = 1 ; b ; b>>=1 , a = a * a %Mod) 
 79     if(b&1) ret = ret*a%N;////+=要比加快。。。。。也可以写成ret*=a;  ret %=a;
 80     return ret; 
 81 }
 82 */
 83 
 84 mtx f(int b)
 85 {
 86     mtx t;
 87     mtx haha ;
 88     haha.a[0][0] = haha.a[0][1] = haha.a[1][0] = 1;
 89     haha.a[1][1] = 0;
 90     
 91     t.a[0][1] = t.a[1][0] = 0;
 92     t.a[1][1] = t.a[0][0] = 1; 
 93     mtx ret ;
 94     //if(b==1)  return t;
 95     for(ret = t ; b ; b>>=1)
 96     {
 97 //    printf("%d\n", b);
 98         if(b&1) ret = ret * haha ;
 99         haha = haha * haha; 
100     } 
101     return ret;
102 } //快速幂矩阵 
103 
104 
105 int main()
106 {
107     int cnt ; 
108     while(~scanf("%d",&cnt)&&cnt!=-1)
109     {
110         mtx ans;
111         ans = f(cnt-1);
112     //    printf("%d %d\n%d %d\n", ans.a[0][0], ans.a[0][1], ans.a[1][0], ans.a[1][1]); 
113         int sum = (1*ans.a[0][0]+1*ans.a[0][1])%N;
114         printf("%d\n",sum);
115     } 
116     return 0 ;
117 } 

 

posted on 2015-07-18 16:15  若流芳千古  阅读(272)  评论(0编辑  收藏  举报

导航