codevs1281 矩阵乘法 快速幂 !!!手写乘法取模!!! 练习struct的构造函数和成员函数
对于这道题目以及我的快速幂以及我的一节半晚自习我表示无力吐槽,,
首先矩阵乘法和快速幂没必要太多说吧,,嗯没必要,,我相信没必要,,实在做不出来写两个矩阵手推一下也就能理解矩阵的顺序了,要格外注意一些细节,比如快速幂时ans矩阵的初始化方式,快速幂的次数,矩阵乘法过程中对临时矩阵的清零,最后输出结果时的初始矩阵。。。矩阵快速幂好理解但是细节还是有点小坑的。。
下面就是满满的槽点,,高能慎入!!!
对于这个题目要求矩阵过程中对m取模,结果对g取模,我表示难以接受,,上来没看清题直接wa19个点,另,经本人实测,在矩阵中直接对m和g取模会直接挂掉,
历经千辛万苦终于改对之后,,发现wa了3个点,,经过eirlys(某坑货)的提示发现过程中乘法会爆long long,于是便一脸mb,脑抽的改成unsign long long后依旧过不了,认真的去看了题解,,然后整个人就呵呵哒了,,题解告诉我要手写快速乘法。。。。。。
真是够了。。。。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 6 struct data { 7 long long f[3][3]; 8 data (void) { 9 memset(f, 0, sizeof(f)); 10 f[0][0] = 1; 11 f[1][1] = 1; 12 f[2][2] = 1; 13 } 14 void clear(void) { 15 memset(f, 0, sizeof(f)); 16 } 17 void print(void) { 18 for (int i = 0; i < 3; i++) { 19 for (int j = 0; j < 3; j++) printf("%lld ", f[i][j]); 20 printf("\n"); 21 } 22 printf("\n"); 23 } 24 }; 25 26 long long m, a, c, x0, n, g; 27 data cur; 28 29 long long mu (long long a1, long long a2) { 30 long long ans = 0; 31 while (a2 > 0) { 32 if (a2 & 1) ans = (ans + a1) % m; 33 a1 = (a1 + a1) % m; 34 a2 >>= 1; 35 } 36 return (ans); 37 } 38 39 data operator * (data a1, data a2) { 40 data t; 41 t.clear(); 42 for (int i = 0; i < 3; i++) 43 for (int j = 0; j < 3; j++) 44 for (int k = 0; k < 3; k++) { 45 t.f[i][j] = (t.f[i][j] + mu(a1.f[i][k], a2.f[k][j]) % m) % m; 46 } 47 return (t); 48 } 49 50 data qpow(data x, long long v) { 51 data ans; 52 while (v > 0) { 53 if (v & 1) ans = ans * x; 54 x = x * x; 55 v >>= 1; 56 } 57 return (ans); 58 } 59 60 int main () { 61 scanf("%lld %lld %lld %lld %lld %lld", &m, &a, &c, &x0, &n, &g); 62 cur.clear(); 63 cur.f[1][0] = 1; 64 cur.f[1][1] = a % m; 65 cur.f[2][1] = 1; 66 cur.f[2][2] = 1; 67 cur = qpow(cur, n); 68 //cur.print(); 69 long long ans = (mu(x0,cur.f[1][1]) % m + mu(c, cur.f[2][1] % m)) % m; 70 ans = ((ans % g) + g) % g; 71 printf("%lld", ans); 72 return 0; 73 }