题意:
Fibonacci数列,f[0]=0, f[1]=1, f[n] = f[n-2]+f[n-1],n>1
给出n(0 <= n < 2^32)和m,求f[n] mod m.
解题思路:
n太大,所以不能用O(n)的循环递推计算
结论:对于矩阵|1 1|,和矩阵|Fn
于是我们就可以用O(logn)的快速幂求模+矩阵乘法算出f[n].
快速幂的过程:a^b =
1, b==0
a, b==1
a^(b/2) * a^(b/2), b 为偶
a*a^(b-1), b为奇
#include<iostream>
#include<cstdio>
using namespace std;
struct Node
{
int arr[2][2];
}o;
Node MUL(Node a, Node b,const int &m)
{
Node tmp;
tmp.arr[0][0] = (a.arr[0][0]*b.arr[0][0] + a.arr[0][1]*b.arr[1][0]) % m;
tmp.arr[0][1] = (a.arr[0][0]*b.arr[0][1] + a.arr[0][1]*b.arr[1][1]) % m;
tmp.arr[1][0] = (a.arr[1][0]*b.arr[0][0] + a.arr[1][1]*b.arr[1][0]) % m;
tmp.arr[1][1] = (a.arr[1][0]*b.arr[0][1] + a.arr[1][1]*b.arr[1][1]) % m;
return tmp;
}
Node exp(Node mat, int n, const int &m)
{
if(n == 1) return o;
if(n & 1)
{
return MUL(o, exp(mat,n-1,m), m);
}
else
{
Node tmp = exp(mat,n>>1, m);
return MUL(tmp,tmp,m);
}
}
int main()
{
o.arr[0][0] = o.arr[0][1] = o.arr[1][0] = 1; o.arr[1][1] = 0;
int cas;
scanf("%d",&cas);
while(cas --)
{
int n,m;
scanf("%d%d",&n,&m);
if(n == 0)
{
printf("0\n");
continue;
}
Node f = o;
f = exp(f,n,m);
printf("%d\n",f.arr[0][1] % m);
}
}