这道题目够囧,表示公式推了大半天,有一个弯比较难想到。最后推出了公式,代码实现我是实现
得一团糟,出现了几个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,小心了。