[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 }

 

posted @ 2016-10-25 21:21  Kirai  阅读(211)  评论(0编辑  收藏  举报