抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

一道有趣的矩乘题。

题解

显然元辅音可以分开来看,那我们就只看元音。

于是我们就可以很自然地推出ans=i=1n(i+1)pians=\sum_{i=1}^n(i+1)p^i。由于有一个叫重音的东西,所以系数是i+1i+1。直接算会 T(70 分),于是我们就想到了矩阵快速幂。

首先我们当然想到是推 2×22\times 2 的,于是写出初始矩阵[02p]\begin{bmatrix}0 & 2p \end{bmatrix},要转移到[2p3p2+2p]\begin{bmatrix}2p & 3p^2+2p\end{bmatrix}。发现矩阵的系数有变化,无法转移。于是我们就需要添加一格来辅助转移。观察两矩阵的系数变化,我们就不难推出辅助的那个应该填什么:[0p2p][2pp23p2+2p]\begin{bmatrix}0&p&2p\end{bmatrix}\to \begin{bmatrix}2p&p^2&3p^2+2p\end{bmatrix}。于是得出中间矩阵是[1000pp10p]\begin{bmatrix}1&0&0\\0&p&p\\1&0&p\end{bmatrix}

然后就用同样的方法算辅音即可。

代码

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
53
54
55
56
57
58
59
60
61
62
#include <cstring>
#include <cmath>
#include <fstream>

using namespace std;

typedef long long LL;

ifstream fin("word.in");
ofstream fout("word.out");

LL chen[4][4], q, p, n, mod, jg[2][4], tt[4][4];

inline void pow(int aa)
{
while(aa)
{
if(aa & 1)
{
for(int j = 1; j <= 3; ++j)
{
tt[1][j] = 0;
for(int k = 1; k <= 3; ++k)
tt[1][j] = (tt[1][j] + jg[1][k] * chen[k][j] % mod) %mod;
}
memcpy(jg, tt, sizeof(jg));
}
aa >>= 1;
for(int i = 1; i <= 3; ++i)
{
for(int j = 1; j <= 3; ++j)
{
tt[i][j] = 0;
for(int k = 1; k <= 3; ++k)
tt[i][j] = (tt[i][j]+chen[i][k]*chen[k][j]%mod)%mod;
}
}
memcpy(chen, tt, sizeof(chen));
}
}

int main()
{
fin >> q >> p >> n >> mod;
jg[1][1] = (q<<1) % mod;
jg[1][2] = q % mod;
chen[1][1] = chen[2][1] = chen[2][2] = q % mod;
chen[1][3] = chen[3][3] = 1;
pow(n);
LL sumy = jg[1][3];
memset(jg, 0, sizeof(jg));
memset(chen, 0, sizeof(chen));
jg[1][1] = (p<<1) % mod;
jg[1][2] = p%mod;
chen[1][1] = chen[2][1] = chen[2][2] = p % mod;
chen[1][3] = chen[3][3] = 1;
pow(n);
LL sumf = jg[1][3];
LL ans = (sumy * sumf % mod + sumy + sumf) % mod;
fout << ans;
return 0;
}

评论