这个题就是根据上面给出的式子 求出 奇数 偶数时候的 递推式。
奇数时是 f(i) = (f(i-2)*4+1)% M; 偶数时是 f(i) = (f(i-2)*4+2)% M;
然后根据递推式来 构造矩阵。
奇数时候的矩阵是
f(i-2) 1 4 0 f(i) 1
X =
0 0 1 1 0 0
偶数的时候是
f(i-2) 2 4 0 f(i) 2
X =
0 0 1 1 0 0
然后用快速幂加速就OK了。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define MAXN 100
#define INF 1<<30
#define mod 1000007
ll N,M;
struct Matrix
{
int n,m;
ll a[MAXN][MAXN];
void clear(int x=0,int y=0)
{
n=x;
m=y;
memset(a,0,sizeof(a));
}
Matrix operator * (const Matrix &b)const
{
Matrix tmp;
tmp.clear(n,b.m);
for(int i=0; i<n; ++i)
for(int j=0; j<b.m; ++j)
for(int k=0; k<m; ++k)
{
tmp.a[i][j]+=a[i][k]*b.a[k][j];
tmp.a[i][j]%=M;
// printf("%d\n",tmp.a[i][j]);
}
return tmp;
}
void show()
{
for(int i=0; i<n; ++i)
{
for(int j=0; j<m; ++j)
cout<<a[i][j]<<" ";
cout<<endl;
}
}
};
Matrix quickPow(Matrix mat,int n)
{
Matrix res;
res.clear(2,2);
res.a[0][0] = 1;res.a[0][1] = 0;
res.a[1][0] = 0;res.a[1][1] = 1;
while(n)
{
if(n&1) res=res*mat;
mat=mat*mat;
n=n>>1;
}
return res;
}
int main (){
while(scanf("%I64d%I64d",&N,&M) != EOF){
if(N % 2 == 0){
Matrix k;
k.clear(2,2);
k.a[0][0] = 4;k.a[0][1] = 0;
k.a[1][0] = 1;k.a[1][1] = 1;
Matrix one;
one.clear(2,2);
one.a[0][0] = 0;one.a[0][1] = 2;
one.a[1][0] = 0;one.a[1][1] = 0;
N /= 2;
Matrix af = one*quickPow(k,N);
printf("%I64d\n",af.a[0][0]%M);
}
else {
if(N == 1){
printf("%I64d\n",1%M);
continue;
}
Matrix k;
k.clear(2,2);
k.a[0][0] = 4;k.a[0][1] = 0;
k.a[1][0] = 1;k.a[1][1] = 1;
Matrix one;
one.clear(2,2);
one.a[0][0] = 1;one.a[0][1] = 1;
one.a[1][0] = 0;one.a[1][1] = 0;
N /= 2;
Matrix af = one*quickPow(k,N);
printf("%I64d\n",af.a[0][0]%M);
}
}
return 0;
}