1. 程式人生 > >HDU5667—Sequence(對數轉化)

HDU5667—Sequence(對數轉化)

pow 初始化 open printf size fine using cnblogs src

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5667

題目意思:f1=1,i=1

     f2=2 ,i=2

     fi=a^b*f[i-1]^c*f[i-2] i>2

思路:發現a^b,和f[i-1]^c之類的東西,我們很明顯吧這個冪變成乘,很自然的想到對數。問題是對什麽取對數,最後發現對a取對數是合適的。

loga(fi)=loga(a^b*f[i-1]^c*f[i-2])=loga(a^b)+loga(f[i-1]^c)+loga(f[i-2]),我們設k[i]=loga(fi),所以k[i]=b+c*k[i-1]+k[i-2]。我們可以通過矩陣快速冪算出k[n],然後a^k[n]=f[n],可以直接用快速冪算出。

這裏需要註意一下,這裏需要規避a%p=0的情況,需要先把k[n]%(mod-1),這一點我目前還沒辦法證明,在完成矩陣快速冪專題以後,研究數論的時候,可能會對這個進一步研究和證明。

代碼:

技術分享
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cmath>
 6 using namespace std;
 7 #define LL long long
 8 LL p,aa,bb,cc,n,mod; //
mod為p-1 9 struct matrix 10 { 11 LL mat[3][3]; 12 }; 13 matrix pow1(matrix a,matrix b) // N^3的矩陣相乘 14 { 15 matrix c; 16 memset(c.mat,0,sizeof(c.mat)); 17 for(int i=0;i<3;i++){ 18 for(int j=0;j<3;j++){ 19 for(int k=0;k<3;k++){ 20 c.mat[i][j] += (a.mat[i][k]*b.mat[k][j]);
21 c.mat[i][j] %= mod; 22 } 23 } 24 } 25 return c; 26 } 27 matrix cheng(matrix a,LL y) //矩陣快速冪 28 { 29 matrix b; 30 memset(b.mat,0,sizeof(b.mat)); 31 for(int i=0;i<3;i++) b.mat[i][i] = 1; 32 while(y){ 33 if(y&1){ 34 b = pow1(a,b); 35 y-=1; 36 }else { 37 a = pow1(a,a); 38 y/=2; 39 } 40 } 41 return b; 42 } 43 LL quick_pow(LL a,LL tmp) //對a進行快速冪 44 { 45 LL b = 1ll; 46 while(tmp) 47 { 48 if(tmp&1) b=(a*b)%p; 49 a=(a*a)%p; 50 tmp>>=1; 51 } 52 return b; 53 } 54 int main() 55 { 56 int t; 57 scanf("%d",&t); 58 while(t--){ 59 scanf("%lld%lld%lld%lld%lld",&n,&aa,&bb,&cc,&p); 60 matrix ma; 61 mod = p-1; 62 memset(ma.mat,0,sizeof(ma.mat));//初始化遞歸矩陣 63 ma.mat[0][0] = cc; ma.mat[0][1] = 1; ma.mat[0][2] = bb; 64 ma.mat[1][0] = 1; ma.mat[2][2] = 1; 65 66 67 ma = cheng(ma,n-2); //算指數和直接冪有點不同 68 LL tmp = ma.mat[0][0]*bb + ma.mat[0][2]; //取出指數 69 LL ans = quick_pow(aa,tmp); 70 printf("%lld\n",ans); 71 72 } 73 return 0; 74 }
View Code

HDU5667—Sequence(對數轉化)