10进制矩阵快速幂-狼胆带你每天头铁一题-算法日常[9/100]

头铁来源

因为狼胆小编本人比较垃圾,所以只能每天带大家头铁一题简单常识题(大佬眼中的常识,我这个蒟蒻还只能头铁),希望能帮助到小白,那就很开心了

题目

题目链接

2019牛客多校5 B题

B_ti

题解

理想中的草稿状态

理想

真实的草稿状态

真实

dreammoon大佬的官方的题解也可以看看

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<bits/stdc++.h>
typedef unsigned long long ULL;
const int SIZE = 3000010;
ULL MOD;
char s[SIZE];
/*矩阵相乘,第一行乘以第一列,第一行乘以第二列……也可以使用for两重循环求*/
void mul(ULL* c1, ULL* c2, ULL *res){
res[0] = (c1[0] * c2[0] + c1[1] * c2[2]) % MOD;
res[1] = (c1[0] * c2[1] + c1[1] * c2[3]) % MOD;
res[2] = (c1[2] * c2[0] + c1[3] * c2[2]) % MOD;
res[3] = (c1[3] * c2[3] + c1[2] * c2[1]) % MOD;
}

int main() {
int a,b;
int x1,x2;
scanf("%d%d%d%d", &x1, &x2, &a, &b);
scanf("%s%llu",s, &MOD);
int len = 0;
/* 统计长度,并且把个位的值(即最后一位的值)减去1 */
for(; s[len]; len++);
s[len-1]--;
/* 个位减掉了之后向前面借位 */
for(int i = len - 1; i >= 0 && s[i] < '0'; i--){
s[i] = '9';
s[i-1]--;
}
ULL now0 = x1, now1 = x2;
ULL d[4][4];
d[0][0] = 0;
d[0][1] = 1;
d[0][2] = b;
d[0][3] = a;
for(int it = len - 1; it >= 0; it--){
memset(d[1], 0, sizeof(ULL) * 12);
/*A "常数"矩阵相乘4次*/
for(int p = 1; p < 4; p++){
mul(d[p-1], d[p-1], d[p]);
}
s[it] -= '0';
for(int p = 0; p < 4; p++){
if((s[it] >> p) & 1){
ULL* ml = d[p];
std::tie(now0, now1) = std::make_pair((ml[0] * now0 + ml[1] * now1) % MOD,(ml[2] * now0 + ml[3] * now1) % MOD);
}
}
mul(d[1], d[3], d[0]);
}
printf("%llu\n", now1);
return 0;
}

少量知识点

tie

pair是tuple的一个子集

每天一句叨叨

今天看到一禅小和尚: 我们尝遍生活的苦,却都只是为了过好平凡的一生

但我觉得如果自己明知道人生是苦,明知道人是基因的机器人(参见算法日常4的叨叨),却认认认真真地选择好好生活,这就是一种伟大,这就是自由,这就是自己的突破,就是自己的英雄!