poj3070
用二分法求矩阵幂
先把矩阵的2^x全算出来存入数组的第x位。然后读入n,从右至左遍历数组,能乘则乘,直到把n填满。
View Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define w 10000;
struct Pow2
{
int matrix[2][2];
int num;
} pow2[50];
Pow2 mul(Pow2 &a, Pow2 &b)
{
Pow2 ret;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
{
ret.matrix[i][j] = 0;
for (int k = 0; k < 2; k++)
{
ret.matrix[i][j] += a.matrix[i][k] * b.matrix[k][j] % w;
ret.matrix[i][j] %= w;
}
}
return ret;
}
int work(int n)
{
if (n <= 1)
return n;
n--;
Pow2 temp;
int i = 1;
while (n >= pow2[i].num)
i++;
i--;
temp = pow2[i];
n -= pow2[i].num;
while (n)
{
while (n < pow2[i].num)
i--;
n -= pow2[i].num;
temp = mul(pow2[i], temp);
}
return temp.matrix[0][0];
}
int main()
{
int n;
//freopen("D:\\t.txt", "r", stdin);
pow2[1].matrix[0][0] = 1;
pow2[1].matrix[1][0] = 1;
pow2[1].matrix[0][1] = 1;
pow2[1].matrix[1][1] = 0;
pow2[1].num = 1;
for (int i = 1; i <= 40; i++)
pow2[i + 1] = mul(pow2[i], pow2[i]);
for (int i = 1; i <= 40; i++)
pow2[i + 1].num = pow2[i].num * 2;
while (scanf("%d", &n) != EOF && n != -1)
printf("%d\n", work(n));
return 0;
}