集训第六周 矩阵快速幂 K题

Description

In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. For example, the first ten terms of the Fibonacci sequence are:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …

An alternative formula for the Fibonacci sequence is

.

Given an integer n, your goal is to compute the last 4 digits of Fn.

Input

The input test file will contain multiple test cases. Each test case consists of a single line containing n (where 0 ≤ n ≤ 1,000,000,000). The end-of-file is denoted by a single line containing the number −1.

Output

For each test case, print the last four digits of Fn. If the last four digits of Fn are all zeros, print ‘0’; otherwise, omit any leading zeros (i.e., print Fn mod 10000).

Sample Input

0
9
999999999
1000000000
-1

Sample Output

0
34
626
6875


1.使用一个结构体存下矩阵,再写一个二维矩阵乘法函数

2.然后求[1 1 1 0]的n次方?当然不是。

注意:0 ≤ n ≤ 1,000,000,000

如果这样直接乘以n次肯定会超时

 

可以使用二进制求快速幂

利用二进制求指数幂

举例:

3 ^ 999 = 3 * 3 * 3 * … * 3

直接乘要做998次乘法。但事实上可以这样做,先求出2^k次幂:

3 ^ 2 = 3 * 3

3 ^ 4 = (3 ^ 2) * (3 ^ 2)

3 ^ 8 = (3 ^ 4) * (3 ^ 4)

3 ^ 16 = (3 ^ 8) * (3 ^ 8)

3 ^ 32 = (3 ^ 16) * (3 ^ 16)

3 ^ 64 = (3 ^ 32) * (3 ^ 32)

3 ^ 128 = (3 ^ 64) * (3 ^ 64)

3 ^ 256 = (3 ^ 128) * (3 ^ 128)

3 ^ 512 = (3 ^ 256) * (3 ^ 256)

再相乘:

3 ^ 999

= 3 ^ (512 + 256 + 128 + 64 + 32 + 4 + 2 + 1)

= (3 ^ 512) * (3 ^ 256) * (3 ^ 128) * (3 ^ 64) * (3 ^ 32) * (3 ^ 4) * (3 ^ 2) * 3

把999转为2进制数:1111100111,其个位就是要乘的数。

1   pow ← 1

2   while (n > 0)

3      do if (n mod 2 = 1)

4            then pow ← pow * x

5        x ← x * x

6        n ← n / 2

7      return pow

 

#include"iostream"
#include"cstdio"
using namespace std;

typedef struct
{
    int m[2][2];
}node;

node work(node a,node b)
{
    node c;
    c.m[0][0]=(a.m[0][0]*b.m[0][0]+a.m[0][1]*b.m[1][0])%10000;
    c.m[0][1]=(a.m[0][0]*b.m[0][1]+a.m[0][1]*b.m[1][1])%10000;
    c.m[1][0]=(a.m[1][0]*b.m[0][0]+a.m[1][1]*b.m[1][0])%10000;
    c.m[1][1]=(a.m[1][0]*b.m[0][1]+a.m[1][1]*b.m[1][1])%10000;
    return c;
}

void caculate(int c)
{
    node ans,base;
    base.m[0][0]=base.m[1][0]=base.m[0][1]=1;
    base.m[1][1]=0;
    ans.m[0][0]=ans.m[1][1]=1;
    ans.m[0][1]=ans.m[1][0]=0;
    while(c)
    {
        if(c&1) ans=work(ans,base);
        base=work(base,base);
        c>>=1;
    }
    cout<<ans.m[1][0]<<endl;
}

int main()
{
    int n;
    while(cin>>n&&n>=0)
    {
        caculate(n);
    }
}
View Code

 


posted @ 2015-08-22 15:32  江南何采莲  阅读(200)  评论(0编辑  收藏  举报