CF678D Iterated Linear Function

CF678D Iterated Linear Function

题意

$f_{i,x}=A\times f_{i-1,x} + B$ 且 $f_{0,x}=x$ 求 $f_{n,x}$。

思路

这道题的递推关系十分清晰。但由于数据范围大($1\le A,B,x\le 10^ 9,1\le n \le 10^{18}$),所以这道题只能使用矩阵乘法加速递推。

矩阵的构造

我们需要构造一个矩阵 $P$,使得 $\begin{bmatrix} f_{0,x}& b\\ 0&0 \end{bmatrix}\times P= \begin{bmatrix} f_{1,x}&b\\ 0&0 \end{bmatrix}$。根据矩阵乘法的规则,我们可以很容易地推出 $P=\begin{bmatrix} A&0\\ 1&1\end{bmatrix}$。由于 $f_{0,x}=x$,所以要得到 $f_{n,x}$ 就可以转化为求 $\begin{bmatrix} x& b\\ 0&0 \end{bmatrix}\times P^n = \begin{bmatrix} f_{n,x}&b\\ 0&0 \end{bmatrix}$,使用矩阵快速幂解决。

code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e9 + 7;
int m, n, x, y, a, b;
struct arr {
    int a[15][15];
    arr() {memset(a, 0, sizeof a);}
    arr operator*(const arr& B) const {//重载乘法
        arr cur;
        int r;
        for (int i = 1; i <= 2; ++i)
            for (int k = 1; k <= 2; ++k) {
                r = a[i][k];
                for (int j = 1; j <= 2; ++j)
                    cur.a[i][j] += B.a[k][j] * r, cur.a[i][j] %= mod;
            }
        return cur;
    }
    arr operator^(int x) const {//重载快速幂
        arr cur, res;
        for (int i = 1; i <= 2; ++i) cur.a[i][i] = 1;
        for (int i = 1; i <= 2; ++i)
            for (int j = 1; j <= 2; ++j) res.a[i][j] = a[i][j] % mod;
        while (x) {
            if (x & 1) cur = cur * res;
            res = res * res;
            x >>= 1;
        }
        return cur;
    }
} A, F;//A对应上文中的P矩阵,F为答案矩阵
int mode(int x, int m) {return (x + m) % m;}
void init() {//初始化
    A.a[1][1] = a, A.a[1][2] = 0;
    A.a[2][1] = 1, A.a[2][2] = 1;
    F.a[1][1] = x, F.a[1][2] = b;
    F = F * (A ^ n);
}
signed main() {
    scanf("%lld%lld", &a, &b);
    scanf("%lld", &n);
    scanf("%lld", &x);
    init();
    printf("%lld", mode(F.a[1][1], mod));
    return 0;
}
posted @ 2023-06-17 08:26  固态H2O  阅读(1)  评论(0编辑  收藏  举报  来源