Loading

CF1182E 名字太长不想打 题解

题解区都是用矩阵直接算封闭形式中 \(f_1,f_2,f_3\) 的系数的,这里给个更偏 MO 风格且好写的做法。

首先先想办法用 \(f_x \cdot k(x)\)\(f_x\) 以消掉 \(c^{2x-6}\) 这个不好处理的东西。

明显 \(k(x)\)\(c^{ax+b}\) 的形式,代进去对比系数可以发现 \(a=1,b=0\)

于是 \(f_x \cdot c^{x} = (f_{x-1}\cdot c^{x-1}) (f_{x-2}\cdot c^{x-2})(f_{x-3}\cdot c^{x-3})\),这是一个很好看的形式。

做个换元,\(h_x=f_x \cdot c^{x}\)\(h\) 的前三项可以以 \(f\) 算出。

我们知道取个 \(\ln\) 就是标准矩乘形式,但是显然没必要。在矩乘中用乘方代替乘号,用乘法代替加法,就可以直接做这种东西了。事实上就是取个指数后的普通矩乘。

换句话说,我们的矩阵上递推的是指数。

这样能大大减少代码量,至于速度,我还没试(

由于我的矩阵用的是模板,代码达到了 2k,然而核心部分非常短。

随便写不卡常就有 45ms,轻松跑进第一页,吊打那些上百毫秒的每一项单独递推。

核心部分长这个样:

signed main(){
    scanf("%lld %lld %lld %lld %lld", &n, &f1, &f2, &f3, &c);
    int h0 = 1ll * f3 * qpow(c, 3) % mod,
        h1 = 1ll * f2 * qpow(c, 2) % mod,
        h2 = 1ll * f1 * qpow(c, 1) % mod;
    matrix tran(3, 3);
    tran[0][0] = tran[0][1] = tran[1][0] = tran[1][2] = tran[2][0] = 1;
    tran = tran ^ (n-1);
    int ans = 1ll * qpow(h0, tran[0][2]) * qpow(h1, tran[1][2]) % mod
                  * qpow(h2, tran[2][2]) % mod;
    ans = 1ll * ans * qpow(inv(c), n % phi) % mod;
    printf("%lld\n", ans);
}

完整代码见 ,也只是多一些矩阵板子和快速幂板子。

注意因为矩阵递推的是指数,矩阵运算时要膜 \(\varphi(mod) = mod-1\)

这道题的十几篇题解几乎都是又慢又难写的每项分开矩乘,唯一的一篇与我的思路相同的还是靠灵感发现能够做此变换,实在令人感慨。

posted @ 2022-09-28 22:16  purplevine  阅读(14)  评论(0编辑  收藏  举报