HDU5667—Sequence(对数转化)
Posted xiaowuga
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU5667—Sequence(对数转化)相关的知识,希望对你有一定的参考价值。
题目链接: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 }
以上是关于HDU5667—Sequence(对数转化)的主要内容,如果未能解决你的问题,请参考以下文章