一道有趣的矩乘题。
题解
显然元辅音可以分开来看,那我们就只看元音。
于是我们就可以很自然地推出ans=∑i=1n(i+1)pi。由于有一个叫重音的东西,所以系数是i+1。直接算会 T(70 分),于是我们就想到了矩阵快速幂。
首先我们当然想到是推 2×2 的,于是写出初始矩阵[02p],要转移到[2p3p2+2p]。发现矩阵的系数有变化,无法转移。于是我们就需要添加一格来辅助转移。观察两矩阵的系数变化,我们就不难推出辅助的那个应该填什么:[0p2p]→[2pp23p2+2p]。于是得出中间矩阵是⎣⎢⎡1010p00pp⎦⎥⎤。
然后就用同样的方法算辅音即可。
代码
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; }
|