。。。题意在这里。
http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=571&pid=1002
我找出来的规律为 ai+1=ai +2,然后我就用矩阵快速幂。。两个数相乘的时候爆掉范围。。
所以要把乘法变成加法快速幂。。
在矩阵快速幂的基础上再加法快速幂。
代码。
//author: CHC //First Edit Time: 2015-03-14 19:37 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <set> #include <vector> #include <map> #include <queue> #include <set> #include <algorithm> #include <limits> using namespace std; typedef unsigned long long ULL; //typedef unsigned __int64 LL; const int MAXN=2; ULL MOD; ULL quickadd(ULL a,ULL b){ ULL ans=0; while(a>0){ if(a&1)ans=(ans+b)%MOD; a>>=1; b=(b+b)%MOD; } return ans; } //C=A*B void mul(ULL A[][MAXN],ULL B[][MAXN],ULL C[][MAXN]){ ULL tmp[MAXN][MAXN]; memset(tmp,0,sizeof(tmp)); for(int i=0;i<MAXN;i++){ for(int j=0;j<MAXN;j++){ for(int k=0;k<MAXN;k++){ //tmp[i][j]+=(A[i][k]*B[k][j])%MOD; tmp[i][j]+=quickadd(A[i][k],B[k][j])%MOD; tmp[i][j]%=MOD; } } } for(int i=0;i<MAXN;i++){ for(int j=0;j<MAXN;j++){ C[i][j]=(tmp[i][j]+MOD)%MOD; } } } ULL quickpow(ULL n){ if(n==1ULL)return 1ULL%MOD; if(n==2ULL)return 2ULL%MOD; if(n==3ULL)return 6ULL%MOD; ULL ans[][MAXN]={{2ULL,2ULL},{0ULL,0ULL}}; ULL base[][MAXN]={{2ULL,0ULL},{1ULL,1ULL}}; n-=2ULL; while(n>0){ //printf("here\n"); if((n&1ULL)==1ULL)mul(ans,base,ans); mul(base,base,base); n>>=1; } return ans[0][0]%MOD; } int main() { ULL n; while(~scanf("%I64u%I64u",&n,&MOD)){ printf("%I64u\n",quickpow(n)); } //MOD=1e+9 +7; //while(~scanf("%llu",&n)){ //printf("%llu\n",quickpow(n)); //} return 0; }