hdu 4291 A Short problem

http://acm.hdu.edu.cn/showproblem.php?pid=4291

  一道矩阵快速幂的题目,给出递推关系,求目标函数的值。

  对递推的题比较陌生,刚开始的时候直接将快速幂套进去,过了sample以后就果断交上去了,没想到居然wa了。搞了一段时间,认真检查了代码无数次,还是找不到问题。

  然后突然被我想到一个相当大的问题。在直接暴力算的时候,算出一层的结果是已经取模以后的结果,可是题目要的是最终结果取模,如果直接套进去算就会发生偏差。对于最外面一层的的结果模10^9+7,我们需要找到这一层的循环节,曾而降低里面那层得到结果的数据规模。暴力打表,得出最外面一层的循环节大小是222222224。这样还没完,因为求解中有3层,所以我们需要继续求循环节,求得最里面一层的循环节长度是183120。然后,把它们建立成表,做成非递归的形式迭代求解。

代码如下:

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <algorithm>
  5 
  6 using namespace std;
  7 typedef __int64 ll;
  8 const int mod[3] = {1000000007, 222222224, 183120};
  9 const int matSize = 2;
 10 int curMod;
 11 
 12 struct Matrix {
 13     ll val[matSize][matSize];
 14 
 15     Matrix(bool Init = false) {
 16         for (int i = 0; i < matSize; i++) {
 17             for (int j = 0; j < matSize; j++) {
 18                 val[i][j] = 0;
 19             }
 20             if (Init) val[i][i] = 1;
 21         }
 22     }
 23 
 24 
 25     void print() {
 26         for (int i = 0; i < matSize; i++) {
 27             for (int j = 0; j < matSize; j++) {
 28                 printf("%I64d ", val[i][j]);
 29             }
 30             puts("");
 31         }
 32         puts("~~~");
 33     }
 34 } Base;
 35 
 36 Matrix operator * (Matrix _a, Matrix _b) {
 37     Matrix ret = Matrix();
 38 
 39     for (int i = 0; i < matSize; i++) {
 40         for (int k = 0; k < matSize; k++) {
 41             if (_a.val[i][k]) {
 42                 for (int j = 0; j < matSize; j++) {
 43                     ret.val[i][j] += (_a.val[i][k] * _b.val[k][j]) % curMod;
 44                     ret.val[i][j] %= curMod;
 45                 }
 46             }
 47         }
 48     }
 49 
 50     return ret;
 51 }
 52 
 53 Matrix operator ^ (Matrix _a, ll _p) {
 54     Matrix ret = Matrix(true);
 55 
 56     while (_p) {
 57         if (_p & 1) {
 58             ret = ret * _a;
 59         }
 60         _a = _a * _a;
 61         _p >>= 1;
 62     }
 63 
 64     return ret;
 65 }
 66 
 67 void initBase(ll _k = 1, ll _a = 3) {
 68     Base.val[0][1] = _k;
 69     Base.val[1][1] = _a;
 70     Base.val[0][0] = 0;
 71     Base.val[1][0] = 1;
 72 }
 73 
 74 ll fun(ll _x, int modKind) {
 75     Matrix ret = Matrix();
 76 
 77     curMod = mod[modKind];
 78     ret.val[0][0] = 0;
 79     ret.val[0][1] = 1;
 80 
 81     ret = ret * (Base ^ _x);
 82 //    ret.print();
 83 
 84     return ret.val[0][0];
 85 }
 86 
 87 ll deal(ll _x) {
 88     ll ret = _x;
 89 
 90     for (int i = 2; i >= 0; i--) {
 91         ret = fun(ret, i);
 92     }
 93 
 94     return ret;
 95 }
 96 
 97 int main() {
 98     ll n;
 99 //    Matrix tmp = Matrix(true);
100 
101     initBase();
102 //    Base.print();
103     /*
104     for (ll i = 0; ; i++) {
105         int last = tmp.val[0][0];
106 
107         tmp = tmp * Base;
108         if (last == 0 && tmp.val[0][0] == 1) {
109             printf("reach %I64d\n", i);
110         }
111     }
112     */
113     while (~scanf("%I64d", &n)) {
114         printf("%I64d\n", deal(n));
115     }
116 
117     return 0;
118 }

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/hdu_4291_Lyon.html