Luogu 1397 [NOI 2013] 矩阵游戏

2023-05-16

          • 传送门
          • 思路
          • 正解
          • 参考代码
          • Remarks

传送门
思路

唉,我太弱了,T1 都做不来,唉,我太弱啦!

显然这个题可以用矩阵快速幂在 O(logn) O ( log ⁡ n ) 的时间复杂度内解决。这里的 n n 106 logn log ⁡ n 3.3×106 3.3 × 10 6 ,但是不要忘了我们只能用高精度来存储这个数,这样我们的时间复杂度就变成了 O(n18logn) O ( n 18 log ⁡ n ) ,显然不能这么做。

观察发现,最后的结果仅要求给出在模 109+7 10 9 + 7 的意义下的值,又观察递推式,发现 f(x) f ( x ) 仅由 f(x1) f ( x − 1 ) 决定,这意味着 f(x) f ( x ) 在模意义下存在循环,且循环节长度至多为 109+7 10 9 + 7 。另外, f(1) f ( 1 ) 一定包含在循环内。

这意味着,如果我们知道了循环节长度,那么这道题就做出来了。当 a=1 a = 1 时( c c d 同理,这里我们用 a a b 来讨论),根据学习 Pólya 定理时的经验,我们知道循环节长度为 109+7gcd(a,109+7) 10 9 + 7 gcd ( a , 10 9 + 7 ) ,由于模数是个质数,因此循环节长度就是 109+7 10 9 + 7

a1 a ≠ 1 时,又该怎么做呢?我太弱了,什么都不会,于是随便选了几个数打了一个表(用 Folyd 判圈法),发现循环节长度要么为 109+6 10 9 + 6 ,要么为它的一半。由于计算一次需要花费数秒时间,因此这不大可能是全部情况。另外,由于 f(1) f ( 1 ) 一定在循环内,因此这里的循环节指的是除去一开始的 1 1 ,当前数又一次变成 1 所需的步数。

然后因为我太弱了,所以其它的都不会做了。唉,我太弱啦!

正解

按照上面的思路,显然我们可以猜想一个做法:对于 a=1 a = 1 的情况,我们将 n n 109+7 取模;对于 a1 a ≠ 1 的情况,我们将 n n 109+6 取模(因为观察到循环节是 109+6 10 9 + 6 的因数)。这样做过后,我们就能通过此题了。唉,发现了因数的关系,却没有想到以 109+6 10 9 + 6 为模数,我太弱啦!

粗略看了一下,网上居然没有针对指数取模的矩阵快速幂的题解,要不就是神仙们说矩阵也满足费马小定理,他们也不用证明,太强啦!唉,我太弱啦!

关键是,我又看错题了,所以上面的白写了,唉,我太弱啦!


先不管看错题的问题。现在的问题是,如何证明递推式 f(n)=af(n1)+b f ( n ) = a f ( n − 1 ) + b 当系数 a a 不为 1 时循环节的长度是 109+6 10 9 + 6 的因数。(当 a=1 a = 1 时根据经验,其实我们已经解决了,所以我们先只考虑 a1 a ≠ 1 的情况)

我们来看递推公式 f(n)=af(n1)+b f ( n ) = a f ( n − 1 ) + b 。我们还是来推导一下通项公式:

f(n)+1a1b=af(n1)+aa1b f ( n ) + 1 a − 1 b = a f ( n − 1 ) + a a − 1 b
f(n)+1a1bf(n1)+1a1b=a f ( n ) + 1 a − 1 b f ( n − 1 ) + 1 a − 1 b = a
f(n)+1a1bf(1)+1a1b=an1 f ( n ) + 1 a − 1 b f ( 1 ) + 1 a − 1 b = a n − 1
f(n)=an1+(an11)ba1 f ( n ) = a n − 1 + ( a n − 1 − 1 ) b a − 1

观察与 n n 有关的东西,只存在于 a 的指数。由费马小定理, a109+61(mod109+7) a 10 9 + 6 ≡ 1 ( mod 10 9 + 7 ) ,因此每 109+6 10 9 + 6 次操作一定会回到起点。故我们可以将矩阵乘法的指数模上 109+6 10 9 + 6

同样我们用数列的知识来看看为什么当 a=1 a = 1 时指数要模 109+7 10 9 + 7 。这时原递推公式对应的数列就从一个类似于等比数列的东西变成了一个等差数列,其通项公式为:

f(n)=(n1)×b+f(1) f ( n ) = ( n − 1 ) × b + f ( 1 )

n n 有关的东西只存在于 b 的系数。由模意义下的乘法, ab(amod(109+7))×b(mod109+7) a b ≡ ( a mod ( 10 9 + 7 ) ) × b ( mod 10 9 + 7 ) 。故在 a=1 a = 1 时循环节变成了 109+7 10 9 + 7


我之前看成了下面的位置是由正上方的位置推导出来的,结果是第一个是由上一行的最后一个推导出来的。不过这并不影响循环节的性质:我们现在可以构造一个可计算的矩阵使得从某一行的第一个数转移到最后一个数,把它再乘上 cd c d 的转移矩阵,就得到了从某一行的第一个数推导出下一行的第一个数的矩阵。显然的是(你手算一下,发现第二行确实如此),这个矩阵的形状如下:

[x0y1] [ x y 0 1 ]

因此它仍然代表着一个 f(i)=xf(i1)+y f ( i ) = x f ( i − 1 ) + y ,循环节仍然存在。不过需要注意的是,第二步就不能通过 c c 特判 1,而要通过上面的 x x 特判 1

参考代码
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cassert>
#include <cctype>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <list>
#include <functional>
typedef long long LL;
typedef unsigned long long ULL;
using std::cin;
using std::cout;
using std::endl;
typedef LL INT_PUT;
INT_PUT readIn()
{
    INT_PUT a = 0; bool positive = true;
    char ch = getchar();
    while (!(ch == '-' || std::isdigit(ch))) ch = getchar();
    if (ch == '-') { positive = false; ch = getchar(); }
    while (std::isdigit(ch)) { a = a * 10 - (ch - '0'); ch = getchar(); }
    return positive ? -a : a;
}
void printOut(INT_PUT x)
{
    char buffer[20]; int length = 0;
    if (x < 0) putchar('-'); else x = -x;
    do buffer[length++] = -(x % 10) + '0'; while (x /= 10);
    do putchar(buffer[--length]); while (length);
}

const int mod = int(1e9) + 7;
const int maxn = int(1e6) + 5;
char strn[maxn];
char strm[maxn];
LL n, m;
int a, b, c, d;

struct Matrix
{
    int c[2][2];
    Matrix() : c() {}
    Matrix(bool unit) : c()
    {
        c[0][0] = c[1][1] = 1;
    }
    int* operator[](int x) { return c[x]; }
    const int* operator[](int x) const { return c[x]; }
    Matrix operator*(const Matrix& b) const
    {
        Matrix ret;
        for (int i = 0; i < 2; i++)
            for (int k = 0; k < 2; k++) if (c[i][k])
                for (int j = 0; j < 2; j++)
                    ret[i][j] = (ret[i][j] + (LL)c[i][k] * b[k][j]) % mod;
        return ret;
    }
    Matrix operator^(int y) const
    {
        Matrix ret(true);
        Matrix x(*this);
        while (y)
        {
            if (y & 1) ret = ret * x;
            x = x * x;
            y >>= 1;
        }
        return ret;
    }
} matrix, nextline;

void run()
{
    scanf("%s%s", strn, strm);
    a = readIn();
    b = readIn();
    c = readIn();
    d = readIn();
    int tempMod;
    tempMod = mod - (a != 1);
    for (char* ch = strm; *ch; ch++)
        m = (((m << 3) + (m << 1)) + (*ch - '0')) % tempMod;
    m = (m - 1 + tempMod) % tempMod;

    matrix[0][0] = a;
    matrix[0][1] = b;
    matrix[1][0] = 0;
    matrix[1][1] = 1;
    matrix = matrix ^ m;

    nextline[0][0] = c;
    nextline[0][1] = d;
    nextline[1][0] = 0;
    nextline[1][1] = 1;
    nextline = matrix * nextline;

    tempMod = mod - (nextline[0][0] != 1); // note: nextline[0][0] 相当于是新的递推式的系数,所以必须在这里判断是否为 1!直接判断 c 是错的!
    for (char* ch = strn; *ch; ch++)
        n = (((n << 3) + (n << 1)) + (*ch - '0')) % tempMod;
    n = (n - 1 + tempMod) % tempMod;

    matrix = (nextline ^ n) * matrix;
    printOut((matrix[0][0] + matrix[0][1]) % mod);
}

int main()
{
    run();
    return 0;
}

/* input
34578734657863487 38465873465876348 1 23734637 3892734 3849
*/
/* output
467549493
*/
Remarks

暴力不要在二进制下进行,要在十进制下进行,这样的话就不用高精度了,时间复杂度为 O(80n) O ( 80 n ) ,被卡常得到 0 0 <script type="math/tex" id="MathJax-Element-65">0</script> 分。

还可以用通项公式(高一数列内容),然后用逆元来做。然而我太弱了,什么都不会。神仙们都是直接十进制快速幂过了,或者用一个没有证明的矩阵费马小定理(说白了就是错的),太强啦!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Luogu 1397 [NOI 2013] 矩阵游戏 的相关文章

  • Luogu 3642 [APIO 2016] 烟火表演

    传送门引例 xff08 上一道题 xff09 凸函数一开始的思路正解参考代码总结 传送门 引例 xff08 上一道题 xff09 凸函数 回忆我们上一道题是怎么做的 我们维护的东西的实质是一个 xff08 下 xff09 凸函数 由于我们的
  • Luogu 3631 [APIO 2011] 方格染色

    传送门思路参考代码细节 传送门 思路 很不错的一道题 xff0c 用到的东西不深 xff0c 但是要想到确实需要一定思维 一开始我想的是动态规划 xff0c 发现如果要设状态需要知道一个格子左边 xff0c 上边和左上边三个格子的状态 然后
  • Luogu 3632 [APIO 2011] 寻路

    传送门正解参考代码 传送门 正解 暴力连边跑最短路就好了 xff0c 只不过代码太长太难写啦 xff01 参考代码 span class hljs preprocessor include lt cstdio gt span span cl
  • Luogu 3634 [APIO 2012] 守卫

    传送门思路正解参考代码 传送门 思路 感觉自己越来越笨了 首先 xff0c 很明显这道题需要把没有看到忍者的区间给删去 xff0c 可以用前缀和 O n O n 处理 xff0c 然后对没有删去的地方重新标号 重新标号时 xff0c 需要对
  • Luogu 1552 [APIO 2012] 派遣

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 题读错了两次 xff0c 一开始读成了一个一般的背包 xff0c 然后读成了一个价值和花费相同的背包 xff0c 最后才发现原来是一个价值为 1
  • 贪玩 CF 之旅

    文章目录 CF 7D Palindrome Degree http codeforces com problemset problem 7 D 题解 CF 713C Sonya and Problem Wihtout a Legend ht
  • Luogu 3638 [APIO 2013] 机器人

    传送门思路正解参考代码关于 SPFA 传送门 思路 n n 这么小 会不会是搜索题 稍有经验的我直接否定了这个结论 仔细读题并分析样例 发现原来一个位置可以有多个机器人 且机器人行走的时候无视其它机器人 那这个就是一张图啊 可以将这张图预处
  • Luogu 3647 [APIO 2014] 连珠线

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 又看错题了 题目中说一个新的珠子和一个已经添加的珠子连接起来 xff0c 我没有看到 xff0c 然后就凉了 立个 flag xff1a 已经连续看错五题了 xff0c
  • 【转】mingw64的安装方法

    转自 xff1a http write blog csdn net postlist mingw64的安装方法 1 下载ming w64 http sourceforge net projects mingw w64 files or x8
  • Luogu 3645 [APIO 2015] 雅加达的摩天楼

    传送门思路正解参考代码Update 传送门 思路 唉 xff0c 我太弱了 xff0c 我都看出来要分块了 xff0c 就是做不来 不过终于把题读对了 先来看子任务三怎么做 显然可以有一个 O m 2 O m 2
  • Luogu 3644 [APIO 2015] 八邻旁之桥

    传送门思路当 k 61 2 时参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 题也做不来 很明显这道题先要把不过河的人排除了 xff0c 剩下的都是要过河的 当 k 61 1 k 61 1 时 xff0
  • Luogu 3646 [APIO 2015] 巴厘岛的雕塑

    传送门总结 APIO 2015思路参考代码总结 传送门 总结 APIO 2015 争取今天做完一套 QAQ T1 我最多之能想到从高位向低位做 xff0c 然后就完全不会了 xff1b T2 我想到了分情况讨论 xff0c 但是没有建图成功
  • UOJ 2016 [APIO 2016] Gap

    传送门思路参考代码交互题 交互题大致形式Windows 平台下 xff08 Dev C 43 43 xff09 Ubuntu 平台下 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 题也做不来 这道题简直就是利用
  • CF 940F Machine Learning

    传送门题目大意思路参考代码Remarks 传送门 题目大意 给你一个数组 a 1 n n 10 5 a 1 n
  • CF 976D Degree Set

    传送门题目大意思路参考代码总结 传送门 题目大意 给你一个长度为 n n 的正整数序列 d 1 d 2 d n d1 d2 dn xff08 d 1 lt d 2 lt lt d n
  • Luogu 3778 [APIO 2017] 商旅

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 看到这道题就想到了二分答案找负环 xff0c 但是怎么做呢 xff1f 完全不会 唉 xff0c 我太弱啦 xff01 先注意题目中说可以重复经过点和边 x
  • CF 963E Circles of Waiting

    传送门题目大意思路参考代码 传送门 题目大意 在平面直角坐标系上 xff0c 有一个神奇的点 xff0c 一开始在 0 0 0 0 每秒钟这个点都会随机移动 xff1a 如果它在 x y
  • CF 976F Minimal k-covering

    传送门题目大意 输入格式输出格式 思路参考代码 传送门 题目大意 给你一张二分图 G 61 U V E G 61 U V
  • CF 963A Alternating Sum

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 好不容易做得来一道题 xff0c 还是 A 题 xff08 所以不要瞧不起 A 题 xff09 xff0c 结果还写错了 xff08 不知道为什
  • iOS中瀑布流布局详解

    前段时间在逛淘宝的时候发现淘宝的商品界面的布局是瀑布流 我记得明明之前不是瀑布流的 x1f611 刚好手上活忙完了 xff0c 写了一个瀑布流的布局 xff0c 简单的封装了下 xff0c 以便日后使用 x1f60f 其实说到底瀑布流也就是

随机推荐

  • Luogu 2146 [NOI 2015] 软件包管理器

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 好不容易遇到一道傻逼题 xff0c 又出了个傻逼错误 xff0c 爆得只剩 30 30 分了 唉 xff0c 我太弱啦 xff01 显然 xff
  • Luogu 2150 [NOI 2015] 寿司晚宴

    传送门思路对于 30 30 30 的数据对于 100 100 100 的数据参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 完全做不来 xff0c 连暴力都打不来 主要好像是因为我从来没有做过以质因子为
  • Luogu 3649 [APIO 2014] 回文串

    传送门思路Manacher 算法 特殊字符回文半径算法与实现本质不同的回文串个数 正解参考代码总结 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 这道题各路神仙都说是模板题 xff0c 但我觉得完全不可做 xf
  • Luogu 2168 [NOI 2015] 荷马史诗

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 连哈夫曼树都不会 这道题就是一个 k k 叉哈夫曼树 题目要求满足两个条件 一是代价最小 二是最长长度最小 最长长度最小很好解决 只需要优先合并
  • Luogu 2178 [NOI 2015] 品酒大会

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 做了两个星期的题 xff0c 自己做出来的才只有这一道 xff0c 唉 xff0c 我太弱啦 xff01 我们考虑第一问怎么做 题目中相似的概念
  • Luogu 1117 [NOI 2016] 优秀的拆分

    传送门思路利用后缀数组解决重复子串问题注意事项参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 连暴力都想不到 xff0c 唉 xff0c 我太弱啦 xff01 考虑暴力法 xff0c 可以枚举一个中间点
  • Luogu 1712 [NOI 2016] 区间

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 这么个傻逼题 xff0c 居然把离散化写错了 xff0c 唉 xff0c 我太弱啦 xff01 显然我们可以考虑枚举最短长度和最长长度 xff0
  • CF 977F Consecutive Subsequence

    传送门思路参考代码 传送门 思路 CF 的第一场 div3 xff0c 在我提交了一份有错的代码后突然不能提交了 xff0c 在跑什么 System Testing xff0c 我就跟它杠上了 xff0c 直到它评测完 唉 xff0c 我太
  • CF 7D Palindrome Degree

    传送门思路参考代码 传送门 思路 不是马拉车加随便 DP 乱搞 xff1f 本来想复习一下马拉车的 xff0c 结果拉出了许多事端 xff08 修复了 OI Learner Judge 的严重 bug 一个害我调了两节课的 bug xff0
  • Luogu 3822 [NOI 2017] 整数

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 当年网同这道题还拿了 16 16 分 xff0c 现在一分都不会做了 xff0c 唉 xff0c 我太弱啦 xff01 这道题其实是很不错的 x
  • 【Go】go语言中切片的长度变化后容量的变化

    一 新增信息长度 43 当前长度 lt 61 当前容量 span class token keyword func span span class token function printSlice span span class toke
  • APIO 2018 Practice Session T1 Wedding cake

    没有传送门题目大意思路参考代码熟悉环境 没有传送门 题目大意 给你一个长度为 n n 的正整数序列 a i ai xff0c 要求构造出 n n 个小数 使得它们的和为 1 1 xff0c 且每个数小数点后恰好有
  • APIO 2018 Practice Session T3 / CF 936C Lock Puzzle

    传送门题目大意思路参考代码总结 传送门 题目大意 给你一个字符串 origin xff0c 一个字符串 target xff0c 长度均为 n n 要求在 3 n 3n xff08 5 2 n 5 2
  • APIO 2018 游记

    Day 0Day 1Day 2Day 3Day 4 Day 0 早上 4 4 点就上车去机场赶那 7 7 点的飞机 感觉很困 xff0c 所以在飞机上就这么睡过去了 北京是个好地方 xff0c 但是与我无关 下飞机后 xff0c 我们一行人
  • Luogu 2375 [NOI 2014] 动物园

    文章目录 传送门思路参考代码Review 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 连 KMP 也不会 xff0c WA 飞了 xff0c 唉 xff0c 我太弱啦 xff01 首先 xff0c 原始的 K
  • Luogu 2114 [NOI 2014] 起床困难综合症

    传送门思路参考代码 传送门 思路 按位贪心 但是我太弱了 xff0c 明明可以 O n O n 预处理 xff0c 我却只会 O 32 n O
  • Luogu 2354 [NOI 2014] 随机数生成器

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 这么一个傻逼题 xff0c 我却看成了要你构造一种交换方案使得答案最小 xff0c 结果后面的额外交换是题目给定的 唉 xff0c 我太弱啦 x
  • Luogu 2305 [NOI 2014] 购票

    传送门思路别人家的题解弱化的传送门 xff08 Luogu 3994 高速公路 xff09 参考代码 对于没有距离限制的 50 分 参考代码 对于 100 分的数据参考代码Remarks 传送门 思路 唉 xff0c 我太弱了 xff0c
  • Luogu 1224 [NOI 2013] 向量内积

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 听都没有听说过这类题 xff0c 唉 xff0c 我太弱啦 xff01 显然这道题可以在 O n 2 d O n 2
  • Luogu 1397 [NOI 2013] 矩阵游戏

    传送门思路正解参考代码Remarks 传送门 思路 唉 xff0c 我太弱了 xff0c T1 都做不来 xff0c 唉 xff0c 我太弱啦 xff01 显然这个题可以用矩阵快速幂在 O log n O log n