ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[NOI2013] 矩阵游戏 题解

2021-09-25 19:00:15  阅读:154  来源: 互联网

标签:right res matrix int 题解 矩阵 NOI2013 mod


[NOI2013] 矩阵游戏

[NOI2013] 矩阵游戏

各位我是弱智石锤了。

题目可能不是很难但是有点细节要注意。

首先考虑行和列我们分别来看:

  • 对于列的情况我们只需要前一项即可递推。
  • 对于行的情况我们只需要上一项也可递推。

那么本质上题目就提示我们可以只保留一项进行矩阵快速幂。

不妨设答案矩阵是
[ 1 f m ] \left[ \begin{matrix} 1 & f_m \end{matrix} \right] [1​fm​​]
我们考虑首先递推同一行之后再递推列,最后一行单独拿出来处理。
[ [ 1 b 0 a ] m − 1 × [ 1 d 0 c ] ] n − 1 × [ 1 b 0 a ] m − 1 \left[ \left[ \begin{matrix} 1 & b \\ 0 & a \end{matrix} \right] ^ {m - 1} \times \left[ \begin{matrix} 1 & d \\ 0 & c \end{matrix} \right] \right] ^ {n - 1} \times \left[ \begin{matrix} 1 & b \\ 0 & a \end{matrix} \right] ^{m - 1} [[10​ba​]m−1×[10​dc​]]n−1×[10​ba​]m−1
注意 矩阵乘法不满足交换律,所以我们矩阵必须按照顺序进行计算。

之后还有一个问题就是 n , m n, m n,m 实际上是很大的,但是对于矩阵不一定有费马小定理。

我们考虑对于第一个矩阵的 m o d − 1 mod - 1 mod−1 次幂得到的矩阵:
[ 1 b × ( a m o d − 2 + a m o d − 3 + ⋯ + a 0 ) 0 a m o d − 1 ] \left[ \begin{matrix} 1 & b \times (a^{mod - 2} + a^{mod - 3} +\dots + a^0) \\ 0 & a^{mod - 1} \end{matrix} \right] [10​b×(amod−2+amod−3+⋯+a0)amod−1​]
我们发现 a m o d − 1 a^{mod - 1} amod−1 直接使用费马小定理得到是 1 1 1。

对于上面 b × ( a m o d − 2 + a m o d − 3 + ⋯ + a 0 ) b \times (a^{mod - 2} + a^{mod - 3} +\dots + a^0) b×(amod−2+amod−3+⋯+a0) 的部分,我们将里面的东西拿出来得到 a m o d − 1 − 1 a − 1 \dfrac{a^{mod - 1} - 1} {a - 1} a−1amod−1−1​ 。

如果 a = 1 a = 1 a=1 呢?直接带入可以得到当幂是 m o d mod mod 的时候上面的部分是 b × m o d b \times mod b×mod 那么也是单位矩阵了。

我们直接对于这个取模即可。

之后考虑 n n n 的限制,同理我们将
[ 1 b 0 a ] m − 1 × [ 1 d 0 c ] \left[ \begin{matrix} 1 & b \\ 0 & a \end{matrix} \right] ^ {m - 1} \times \left[ \begin{matrix} 1 & d \\ 0 & c \end{matrix} \right] [10​ba​]m−1×[10​dc​]
这个矩阵拿出来,发现左上角同样是 1 1 1 我们可以通过相同的方式得到。


#include <bits/stdc++.h>
using namespace std;

//#define Fread
//#define Getmod

#ifdef Fread
char buf[1 << 21], *iS, *iT;
#define gc() (iS == iT ? (iT = (iS = buf) + fread (buf, 1, 1 << 21, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
#define getchar gc
#endif // Fread

template <typename T>
void r1(T &x) {
	x = 0;
	char c(getchar());
	int f(1);
	for(; c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
	for(; '0' <= c && c <= '9';c = getchar()) x = (x * 10) + (c ^ 48);
	x *= f;
}

template <typename T,typename... Args> inline void r1(T& t, Args&... args) {
    r1(t);  r1(args...);
}

//#define int long long
const int maxn = 2e5 + 5;
const int maxm = maxn << 1;
int n, m;
const int mod = 1e9 + 7;
struct Matrix {
    int a[2][2];
    Matrix(void) { memset(a, 0, sizeof(a)); }
    Matrix operator * (const Matrix &z) const {
        Matrix res;
        for(int i = 0; i < 2; ++ i) {
            for(int j = 0; j < 2; ++ j) {
                for(int k = 0; k < 2; ++ k) {
                    res.a[i][j] = (res.a[i][j] + 1ll * a[i][k] * z.a[k][j] % mod) % mod;
                }
            }
        }
        return res;
    }
}F, tmp1, tmp2;
string sn, sm;
int A, B, C, D;

Matrix ksm(Matrix x,int mi) {
    Matrix res;
    res.a[0][0] = res.a[1][1] = 1;
    while(mi) {
        if(mi & 1) res = res * x;
        mi >>= 1;
        x = x * x;
    }
    return res;
}

signed main() {
//    freopen("S.in", "r", stdin);
//    freopen("S.out", "w", stdout);
    int i, j;
    cin >> sn >> sm;
    r1(A, B, C, D);// A <= C
    int mod1 = ( (A == 1) ? mod : mod - 1 );
    for(i = 0; i < sm.size(); ++ i)
        m = ( 10ll * m + (sm[i] ^ 48) ) % mod1;

//    printf("%d %d\n", n, m);

    F.a[0][0] = F.a[0][1] = 1;
    tmp1.a[0][0] = 1, tmp1.a[1][0] = 0;
    tmp1.a[0][1] = B, tmp1.a[1][1] = A;
    tmp2.a[0][0] = 1, tmp2.a[1][0] = 0;
    tmp2.a[0][1] = D, tmp2.a[1][1] = C;
    tmp1 = ksm(tmp1, m < 1 ? m + mod1 - 1 : m - 1);
    tmp2 = tmp1 * tmp2;
    mod1 = (tmp2.a[1][1] == 1 ? mod : mod - 1);
    for(i = 0; i < sn.size(); ++ i)
        n = ( 10ll * n + (sn[i] ^ 48) ) % mod1;
    F = F * ksm(tmp2, n < 1 ? n + mod1 - 1 : n - 1) * tmp1;
    printf("%d\n", F.a[0][1]);
	return 0;
}
/*
34578734657863487 38465873465876348 1 23734637 3892734 3849

467549493
*/

标签:right,res,matrix,int,题解,矩阵,NOI2013,mod
来源: https://blog.csdn.net/sharp_legendgod/article/details/120475674

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有