Problem A: Modular Fibonacci |
The Fibonacci numbers (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...) are defined by the recurrence:
F0 = 0
F1 = 1
Fi = Fi-1 + Fi-2 for i>1
Write a program which calculates Mn = Fn mod 2m for given pair of n and m. 0� n� 2147483647 and 0� m< 20. Note that a mod b gives the remainder when a is divided by b.
Input and Output
Input consists of several lines specifying a pair of n and m. Output should be corresponding Mn, one per line.
Sample Input
11 7 11 6
Sample Output
89 25题意:给定n和m,求斐波那契数列第Fn %(2 ^ m)
思路:斐波那契数列的矩阵快速幂 [1 1] * [Fn + 1] = [Fn + 1 + Fn = Fn + 2] 这样只要求出[1 1] 这个矩阵的n次方乘上[F2] 就可以得到第Fn项。然后就是矩阵的
[1 0] [Fn] [Fn + 1] [1 0] [F1] 快速幂取模。注意要用longlong
代码:
#include <stdio.h>
#include <string.h>
long long n, mm;
struct ju {
long long m[2][2];
ju() {
memset(m, 0, sizeof(m));
}
} m1, m2, m3, m4;
ju mul(ju a, ju b) {
ju c;
for (int i = 0; i < 2; i ++) {
for (int j = 0; j < 2; j ++) {
for (int k = 0; k < 2; k ++) {
c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j]) % mm;
}
}
}
return c;
}
void mi(long long k) {
m4.m[0][0] = m4.m[1][1] = m1.m[0][0] = m1.m[0][1] = m1.m[1][0] = 1;
m4.m[0][1] = m4.m[1][0] = m1.m[1][1] = 0;
while (k != 1) {
m2 = m1;
m3 = mul(m1, m1);
m1 = m3;
if (k & 1) {
m3 = mul(m4, m2);
m4 = m3;
}
k = k>>1;
}
m3 = mul(m1, m4);
m1 = m3;
}
int main() {
while (~scanf("%lld%lld", &n, &mm)) {
if (n == 0 || mm == 0) {
printf("0\n"); continue;
}
mm = 1<<mm;
mi(n);
printf("%lld\n", m1.m[0][1]);
}
return 0;
}