B - generator 1

题意

给你\(x_{0}、x_{1}、a、b、b、mod\),根据\(x_{i} = a*x_{i-1} + b*x_{i-2}\)求出\(x_{n}\)

思路

一般看到这种题就会想到矩阵快速幂,但是这次的\(n\)太大了,所以要用十进制倍增来算,但是单单用十进制倍增来算应该还会\(TLE\),然后就要用二进制倍增来优化了。

  • 我们要先求出矩阵快速幂的通项式
    \[ \begin{pmatrix}x_{n+1} \\x_{n}\end{pmatrix}= \begin{pmatrix}a & b\\1& 0 \end{pmatrix} \begin{pmatrix}x_{n}\\ x_{n-1}\end{pmatrix}= \begin{pmatrix}a & b\\1& 0 \end{pmatrix}^{n} \begin{pmatrix}x_{1}\\ x_{0}\end{pmatrix}\]
  • 用十进制和二进制优化
for(int i = len-1; i >= 0; i--){
    ans = ans*pow(res, n[i]-'0');
    res = pow(res, 10ll);
}

\(ans = res^{(n[i] - '0')}、(n[i] - '0')\):是当前位的数
\(res = res^{10}\)
就是把\(n\)分解成每一位,然后相乘
例如\(a^{300} = (a^{100})^{3}\) => \(ans = (res^{10})^{n[i]-'0'}\)
计算每一位就可以了
(说的有点混乱,主要是今天突然碰到这种算法很神奇,记录一下~)

AC代码

#include<bits/stdc++.h>
#define mes(a, b) memset(a, b, sizeof a)
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
ll mod;
char n[maxn];
 
struct Mat{
    ll mat[4][4];
    Mat(){
        mes(mat, 0);
    }
    void init(){
        for(int i = 1; i <= 2; i++)
            mat[i][i] = 1;
    }
 
    Mat operator * (const Mat &a)const{
        Mat ans;
        for(int i = 1; i <= 2; i++){
            for(int j = 1; j <= 2; j++){
                for(int k = 1; k <= 2; k++){
                    ans.mat[i][j] += mat[i][k]*a.mat[k][j]%mod;
                    ans.mat[i][j] %= mod;
                }
            }
        }
        return ans;
    }
};

Mat pow(Mat a, ll b){
    Mat ans;
    ans.init();
    while(b){
        if(b&1)
            ans = ans*a;
        a = a*a;
        b >>= 1;
    }
    return ans;
}
 
int main(){
    ll a, b, x1, x0;
    scanf("%lld%lld%lld%lld", &x0, &x1, &a, &b);
    scanf("%s%lld",n, &mod);
    int len = strlen(n);
    Mat ans; ans.init();
    Mat res;
    res.mat[1][1] = a; res.mat[1][2] = b;
    res.mat[2][1] = 1;
    for(int i = len-1; i >= 0; i--){
        ans = ans*pow(res, n[i]-'0');
        res = pow(res, 10ll);
    }
    Mat f;
    f.mat[1][1] = x1;
    f.mat[2][1] = x0;
    f = ans*f;
    printf("%lld\n",f.mat[2][1]);
    return 0;
}