分解

分解

题目链接:http://www.51nod.com/contest/problem.html#!problemId=1537

矩阵快速幂

找规律可知,一定存在m,满足(1+sqrt(2)) ^n=sqrt(m) +sqrt(m-1),但是该如何找到这个m呢?注意到n的范围是1e18,所以只能是O(1)或者O(lgn)的做法。

(1+sqrt(2)) ^n的展开式中只包含整数项和sqrt(2)项,设(1+sqrt(2)) ^n=a+b*sqrt(2),a和b均为正整数。

初始状态当n=1时,a=1,b=1;然后构造出变换矩阵即可。

代码如下:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #define M (long long)(1e9+7)
 5 using namespace std;
 6 typedef long long LL;
 7 struct math{
 8     LL mp[2][2];
 9 }E,A;
10 /*
11 变换矩阵:
12 1 2
13 1 1
14 */
15 math mul_math(math a,math b){
16     math temp;
17     for(int i=0;i<2;++i)
18     for(int j=0;j<2;++j){
19         temp.mp[i][j]=0;
20         for(int k=0;k<2;++k)
21             temp.mp[i][j]+=(a.mp[i][k]*b.mp[k][j])%M;
22     }
23     return temp;
24 }
25 math pow_math(LL x){
26     math base=A,temp=E;
27     while(x){
28         if(x&1)temp=mul_math(temp,base);
29         base=mul_math(base,base);
30         x>>=1;
31     }
32     return temp;
33 }
34 int main(void){
35     for(int i=0;i<2;++i){
36         E.mp[i][i]=1;
37         A.mp[i][i]=1;
38     }
39     A.mp[1][0]=1;
40     A.mp[0][1]=2;
41     LL n;
42     cin>>n;
43     math temp=pow_math(n-1);
44     LL a=(temp.mp[0][0]+temp.mp[0][1])%M;
45     a=(a*a)%M;
46     LL b=(temp.mp[1][0]+temp.mp[1][1])%M;
47     b=(b*b)%M;
48     b=(b+b)%M;
49     cout<<max(a,b)<<endl;
50 }
原文地址:https://www.cnblogs.com/barrier/p/5813457.html