HDU4549 M斐波那契数列 —— 斐波那契、费马小定理、矩阵快速幂

题目链接:https://vjudge.net/problem/HDU-4549

M斐波那契数列

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 4492    Accepted Submission(s): 1397


Problem Description
M斐波那契数列F[n]是一种整数数列,它的定义如下:

F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] ( n > 1 )

现在给出a, b, n,你能求出F[n]的值吗?
 
Input
输入包含多组测试数据;
每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 )
 
Output
对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行。
 
Sample Input
0 1 0 6 10 2
 
Sample Output
0 60
 
Source
 
Recommend
liuyiding

题解:

1.可知f[n]中a、b的指数符合斐波那契数列,因而可用矩阵快速幂求出。

2.然而如果指数不求模,也可能会溢出。但指数又怎样求模呢?

有如下定理:当m为素数,且a、n互质时, a^n % m = a^(n%(m-1)) % m

证明:

根据费马小定理,当m为素数,且a、p互质时, a^(m-1) ≡ 1 (mod m),

a^n = a^(k*(m-1)+r) = (a^(m-1))^k * a^r,其中 r = n%(m-1),

那么 a^n % m = ( (a^(m-1))^k * a^r ) % m =  (a^(m-1))^k % m * a^r % m = 1 * a^r % m = a^(n%(m-1)) % m 。

所以:当m为素数,且a、n互质时, a^n % m = a^(n%(m-1)) % m

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <cmath>
 7 #include <queue>
 8 #include <stack>
 9 #include <map>
10 #include <string>
11 #include <set>
12 using namespace std;
13 typedef long long LL;
14 const int INF = 2e9;
15 const LL LNF = 9e18;
16 const int MOD = 1000000007;
17 const int MAXN = 1e6+100;
18 
19 const int Size = 2;
20 struct MA
21 {
22     LL mat[Size][Size];
23     void init()
24     {
25         for(int i = 0; i<Size; i++)
26         for(int j = 0; j<Size; j++)
27             mat[i][j] = (i==j);
28     }
29 };
30 
31 MA mul(MA x, MA y)
32 {
33     MA ret;
34     memset(ret.mat, 0, sizeof(ret.mat));
35     for(int i = 0; i<Size; i++)
36     for(int j = 0; j<Size; j++)
37     for(int k = 0; k<Size; k++)
38         ret.mat[i][j] += (1LL*x.mat[i][k]*y.mat[k][j])%(MOD-1), ret.mat[i][j] %= (MOD-1);
39     return ret;
40 }
41 
42 MA qpow(MA x, LL y)
43 {
44     MA s;
45     s.init();
46     while(y)
47     {
48         if(y&1) s = mul(s, x);
49         x = mul(x, x);
50         y >>= 1;
51     }
52     return s;
53 }
54 
55 LL q_pow(LL x, LL y)
56 {
57     LL s = 1;
58     while(y)
59     {
60         if(y&1) s *= x, s %= MOD;
61         x *= x, x %= MOD;
62         y >>= 1;
63     }
64     return s;
65 }
66 
67 MA tmp = {
68     1, 1,
69     1, 0
70 };
71 
72 int main()
73 {
74     LL f[2], n;
75     while(scanf("%lld%lld%lld",&f[0],&f[1],&n)!=EOF)
76     {
77         if(n<=1)
78         {
79             printf("%lld
", f[n]%MOD);
80             continue;
81         }
82 
83         MA s = tmp;
84         s = qpow(s, n-1);
85         LL p1 = s.mat[0][0];
86         LL p2 = s.mat[1][0];
87         LL ans = q_pow(f[0], p2)*q_pow(f[1], p1)%MOD;
88         printf("%lld
", ans);
89     }
90 }
View Code
原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8417182.html