[51NOD1537] 分解(递推,矩阵快速幂)
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1537
思路:一开始用二项式拆了一下,发现这个式子的形式总能变成a+b*sqrt(2)的形式。然后就列了几个。
1+1*sqrt(2)
3+2*sqrt(2)
7+5*sqrt(2)
17+12*sqrt(2)
挺明显的:ai=ai-1+2*bi-1,bi=ai-1+bi-1。
转移的矩阵:
1 2
1 1
起初我是怀疑这个题是有bug的,因为输出的结果要取模,但是我的代码是求出了未平方的值,但是这个时候如果平方溢出了呢?再取模会不会有问题?不过仔细一想,平方后对1e9+7取模结果一定小于它,所以它们的相对位置是统一的。推算出结果,判断一发a和b的顺序就行了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const LL mod = (LL)1e9+7; 6 const int maxn = 5; 7 LL n; 8 9 typedef struct Matrix { 10 LL m[maxn][maxn]; 11 int r; 12 int c; 13 Matrix(){ 14 r = c = 0; 15 memset(m, 0, sizeof(m)); 16 } 17 } Matrix; 18 19 Matrix mul(Matrix m1, Matrix m2) { 20 Matrix ans = Matrix(); 21 ans.r = m1.r; 22 ans.c = m2.c; 23 for(int i = 1; i <= m1.r; i++) { 24 for(int j = 1; j <= m2.r; j++) { 25 for(int k = 1; k <= m2.c; k++) { 26 if(m2.m[j][k] == 0) continue; 27 ans.m[i][k] = ((ans.m[i][k] + m1.m[i][j] * m2.m[j][k] % mod) % mod) % mod; 28 } 29 } 30 } 31 return ans; 32 } 33 34 Matrix quickmul(Matrix m, LL n) { 35 Matrix ans = Matrix(); 36 for(int i = 1; i <= m.r; i++) { 37 ans.m[i][i] = 1; 38 } 39 ans.r = m.r; 40 ans.c = m.c; 41 while(n) { 42 if(n & 1) ans = mul(m, ans); 43 m = mul(m, m); 44 n >>= 1; 45 } 46 return ans; 47 } 48 49 int main() { 50 //freopen("in", "r", stdin); 51 while(~scanf("%lld", &n)) { 52 Matrix p; p.c = 2; p.r = 2; 53 p.m[1][1] = 1; p.m[1][2] = 2; 54 p.m[2][1] = 1; p.m[2][2] = 1; 55 Matrix q = quickmul(p, n); 56 LL a = q.m[1][1], b = q.m[2][1]; 57 a = (a * a) % mod; 58 b = (((b * b) % mod) * 2) % mod; 59 if(a == b + 1) printf("%lld\n", a); 60 else if(a + 1 == b) printf("%lld\n", b); 61 else puts("no"); 62 } 63 return 0; 64 }