HDU2971_Tower_求递推式累加

这道题目够囧,表示公式推了大半天,有一个弯比较难想到。最后推出了公式,代码实现我是实现

得一团糟,出现了几个wa,不过最终被我排查出来了,开心~

/*
*State:
*题目大意:
*        先假设a2 = t, 题目给定了递推关系:An = 2 * t * An-1 - An-2 (n > 2),
*        初值A1 = 1, A2 = t;题目要求Sn = An ^ 2 + An-1 ^ 2 + ... + A1 ^ 2。
*解题思路:
*        Sn = An ^ 2 + Sn-1由这个,找出技巧(要推二次)
*        化出:
*            Sn = 4*k^2Sn-1 + (2-8*k^2)Sn-2 + 4*k^2Sn-3 - Sn-4;
*        有了递推式,直接矩阵构造求解吧。
*解题感想:
*        这道题目很容易TLE,还有注意中间结果溢出问题。wa了3次,找了
*        好久问题,最终还是化简了程序得到ac的,挺不容易,但是爽。
*/
View Code
  1 #include <iostream>
  2 #include <cmath>
  3 #define maxn 5
  4 
  5 using namespace std;
  6 
  7 struct Mat
  8 {
  9     int m, n;
 10     __int64 d[maxn][maxn];
 11     void init(int m, int n) 
 12     {
 13         this->m = m;
 14         this->n = n;
 15         memset(d, 0, sizeof(d));
 16     }
 17     void initE(int size)                              //生成单位阵
 18     {
 19         m = n = size;
 20         for(int i = 0; i < n; i ++)
 21         {
 22             for(int j = 0; j < n; j ++)
 23             {
 24                 d[i][j] = i==j;
 25             }
 26         }
 27     }
 28 
 29     Mat operator * (const Mat & mat) const
 30     {
 31         static Mat res;
 32         res.init(m, mat.n);
 33         for(int i = 0; i < res.m; i ++)
 34         {
 35             for(int k = 0; k < n; k ++)
 36             {
 37                 if(d[i][k]==0)    continue;
 38                 for(int j = 0; j < res.n; j ++)
 39                 {
 40                     res.d[i][j] += d[i][k] * mat.d[k][j];
 41                 }
 42             }
 43         }
 44         return res;
 45     }
 46 
 47     Mat mul_mod(const Mat & mat, int mod) const
 48     {
 49         static Mat res;
 50         res.init(m, mat.n);
 51         for(int i = 0; i < res.m; i ++)
 52         {
 53             for(int k = 0; k < n; k ++)
 54             {
 55                 if(d[i][k]==0)    continue;
 56                 for(int j = 0; j < res.n; j ++)
 57                 {
 58                     res.d[i][j]=(res.d[i][j]+d[i][k]*mat.d[k][j]) % mod;
 59                 }
 60             }
 61         }
 62         return res;
 63     }
 64 
 65     void pow_mod(int k, int mod)                      //this = this^k % mod;
 66     {
 67         static Mat a;
 68         a = *this;
 69         for(this->initE(n); k; k>>=1, a=a.mul_mod(a, mod))
 70             if(k&1)    *this=this->mul_mod(a, mod);
 71     }
 72     
 73     //Mat pow_mod(int k, int mod) {                //不破坏原矩阵的版本
 74     //    static Mat a, r;
 75     //    for(a = *this, r.initE(n); k; k>>=1, a=a.mul_mod(a, mod))
 76     //        if(k&1)    r=r.mul_mod(a, mod);
 77     //    return r;
 78     //}
 79     
 80     void view_arr()
 81     {
 82         for(int i = 0; i < m; i++)
 83         {
 84             for(int j = 0; j < n; j++)
 85                 cout << d[i][j] << " ";
 86             cout << endl;
 87         }
 88     }
 89 };
 90 
 91 
 92 int main(void)
 93 {
 94 #ifndef ONLINE_JUDGE
 95     freopen("in.txt", "r", stdin);
 96 #endif
 97     int n, cas;
 98     __int64 mod, k;
 99     scanf("%d", &cas);
100     while(cas--)
101     {
102         scanf("%I64d %d", &k, &n);
103         scanf("%I64d", &mod);
104         __int64 s[5], a3, a4;
105 
106         s[1] = 1, s[2] = (s[1] + (k * k)) % mod;
107         a3 = (2 * k * k - 1) % mod;
108         s[3] = ((a3 * a3) % mod + s[2]) % mod;
109         a4 = (2 * k * a3 - k) % mod;
110         s[4] = ((a4 * a4) % mod + s[3]) % mod;
111 
112         if(n <= 4)
113         {
114             printf("%I64d\n", s[n]);
115             continue;
116         }
117 
118         __int64 b1, b2, b3, b4;
119 
120         b1 = (4 * k * k) % mod;
121         b2 = (2 - (8 * k * k)) % mod;  // 负数取模、、悬
122         b3 = b1;
123         b4 = -1;
124 
125         Mat a;
126         a.init(4, 4);
127         a.d[0][0] = b1, a.d[0][1] = b2, a.d[0][2] = b3, a.d[0][3] = b4;
128         a.d[1][0] = 1, a.d[2][1] = 1, a.d[3][2] = 1;
129         a.view_arr();
130         a.pow_mod(n - 4, mod);
131         cout << "hah" << endl;
132         a.view_arr();
133         __int64 ans = ((a.d[0][0] * s[4]) % mod + (a.d[0][1] * s[3]) % mod
134                 + (a.d[0][2] * s[2]) % mod + (a.d[0][3] * s[1]) % mod) % mod;
135 
136         printf("%I64d\n", ((ans % mod) + mod) % mod);
137     }
138     return 0;
139 }

跑了4000+ms,这个鸭梨比较大,该题很容易TLE,小心了。

原文地址:https://www.cnblogs.com/cchun/p/2619545.html