程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> UVA10518 - How Many Calls?(矩陣快速冪)

UVA10518 - How Many Calls?(矩陣快速冪)

編輯:C++入門知識

UVA10518 - How Many Calls?(矩陣快速冪)


UVA10518 - How Many Calls?(矩陣快速冪)

題目鏈接

題目大意:給你fibonacci數列怎麼求的,然後問你求f(n) = f(n - 1) + f(n - 2)需要多少次調用,並且這個數很大,取模一個進制的數。

解題思路:要發現F(n) = 2 *f(n) - 1這個規律,估計要很熟系fibonacci數列,我明明推出了好多項後但是一點也沒有發現規律。然後要用矩陣快速冪來求fibonacci,因為n很大。構造這樣的矩陣
1, 1 (2*2矩陣) * f(n - 1) (2*1矩陣) 等於 f(n - 1) + f(n - 2)(2*1矩陣)
1, 0 f (n - 2) f(n - 1)


這樣就可以用前面的那麼系數矩陣的n次冪乘上f(1) 這個矩陣得到最後想要的答案。
f(0)

代碼:

#include 
#include 

typedef long long ll;
const int maxn = 2;
int base;

struct Mat {

    int s[maxn][maxn];

    void init () {
        s[0][0] = s[0][1] = s[1][0] = 1;
        s[1][1] = 0;
    }

    Mat operator ^ (const Mat& t) const {

        Mat arr;    
        memset (arr.s, 0, sizeof(arr.s));

        for (int i = 0; i < maxn; i++)
            for (int j = 0; j < maxn; j++)
                for (int k = 0; k < maxn; k++) 
                    arr.s[i][j] = (arr.s[i][j] + s[i][k] * t.s[k][j]) % base;
        return arr; 
    }
};

Mat Fmod (ll n, Mat a) {

    if (n == 1)
        return a; 

    Mat tmp = Fmod(n/2, a);
    tmp = tmp ^ tmp;
    if (n % 2 == 1)
        tmp = tmp ^ a;

/*    printf ("%lld\n", n);
    for (int i = 0; i < maxn; i++)
            printf ("%d %d\n", tmp.s[i][0], tmp.s[i][1]);*/
    return tmp;
}

int main () {

    ll n;
    int cas = 0;
    Mat a, ans;

    while (scanf ("%lld%d", &n, &base) && (n || base)) {

        a.init();
        if (n)
            ans = Fmod(n, a);    
        else
            ans = a;
        printf ("Case %d: %lld %d %d\n", ++cas, n, base, (ans.s[0][0] * 2 + base - 1) % base);
    }
    return 0;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved