[NOI2013]矩阵游戏

题意:对于一个n行m列的矩阵,第i行第j列的元素为F[i][j]。已知a, b, c, d,并且矩阵元素满足:
F[1][1] = 1
F[i,j] = a * F[i][j-1] + b (j!=1)
F[i,1] = c * F[i-1][m] + d (i!=1)
求F[n][m] 答案对1e9 + 7取模
1 <= n, m <= 1e1000000
1 <= a, b, c, d <= 1e9
这道题一眼看上去非常的矩阵快速幂
好像没毛病?
看了眼数据量 哭辽
没关系 我可以10000进制快速幂!(看起来很稳
那就写一写?

// luogu-judger-enable-o2
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>
#pragma GCC optimize("Ofast,no-stack-protector")
using namespace std;
const int N = (int)1e6 + 5;
const int M = 1e3;
const long long P = 1e9 + 7;
inline long long Mod(long long x){
    while(x >= P) x -= P; while(x < 0) x += P;
    return x;
}
struct Matrix{
    long long mat[2][2];
    inline void init(int aa, int ab, int ba, int bb){
        mat[0][0] = aa, mat[0][1] = ab, mat[1][0] = ba, mat[1][1] = bb;
    }
}next1, next2, stot, tot;
    inline Matrix operator *(const Matrix& x, const Matrix& y){
        Matrix z; z.init(0, 0, 0, 0);
        //printf("!!!\n");
        z.mat[0][0] = Mod(z.mat[0][0] + x.mat[0][0] * y.mat[0][0] % P);
        z.mat[0][0] = Mod(z.mat[0][0] + x.mat[0][1] * y.mat[1][0] % P);
        z.mat[0][1] = Mod(z.mat[0][1] + x.mat[0][1] * y.mat[1][1] % P);
        z.mat[0][1] = Mod(z.mat[0][1] + x.mat[0][0] * y.mat[0][1] % P);
        z.mat[1][0] = Mod(z.mat[1][0] + x.mat[1][0] * y.mat[0][0] % P);
        z.mat[1][0] = Mod(z.mat[1][0] + x.mat[1][1] * y.mat[1][0] % P);
        z.mat[1][1] = Mod(z.mat[1][1] + x.mat[1][0] * y.mat[0][1] % P);
        z.mat[1][1] = Mod(z.mat[1][1] + x.mat[1][1] * y.mat[1][1] % P);
        return z;
    }
char n[N], m[N], tn[N], tm[N];
long long a, b, c, d;
inline void init(){
    scanf("%s%s%lld%lld%lld%lld", n, m, &a, &b, &c, &d);
    next1.init(a, b, 0, 1);
    next2.init(c, d, 0, 1);
}
inline Matrix qqp(Matrix x, int y){
    Matrix res; res.init(1, 0, 0, 1);
    while(y){
        if(y & 1) res = res * x;
        x = x * x; y >>= 1;
    }
    return res;
}
inline Matrix qpow(Matrix x, int len, char* y){
    int tmp; Matrix res, tt;
    res.init(1, 0, 0, 1);
    for(int i = 0; i < len; i += 4){
        tmp = 0;
        for(int j = 3; j >= 0; --j)
            tmp = (tmp << 3) + (tmp << 1) + y[i + j] - '0';
        tt = qqp(x, tmp);
        res = res * tt;
        x = qqp(x, 10000);
    }
    return res;
}
inline void debug(Matrix x){
    printf("%lld %lld %lld %lld\n", x.mat[0][0], x.mat[0][1], x.mat[1][0], x.mat[1][1]);
}
int main(int argc, char *argv[])
{
    init(); 
    int ln = strlen(n), lm = strlen(m), ltn, ltm;
    for(int i = ln - 1; i >= 0; --i)
        if(n[i] == '0') n[i] = '9';
        else{n[i] = n[i] - 1; break;}
    for(int i = lm - 1; i >= 0; --i)
        if(m[i] == '0') m[i] = '9';
        else{m[i] = m[i] - 1; break;}
    int it;
    for(it = 0; it < ln && n[it] == '0'; ++it);
    ltn = ln - it; 
    for(; it < ln; ++it) tn[ln - it - 1] = n[it];
    tn[ltn] = tn[ltn + 1] = tn[ltn + 2] = '0';
    tn[ltn + 3] = '\0';
    for(it = 0; it < lm && m[it] == '0'; ++it);
    ltm = lm - it; 
    for(; it < lm; ++it) tm[lm - it - 1] = m[it];
    tm[ltm] = tm[ltm + 1] = tm[ltm + 2] = '0';
    tm[ltm + 3] = '\0';
    stot = qpow(next1, ltm, tm);
    tot = next2 * stot;
    tot = stot * qpow(tot, ltn, tn);
    printf("%lld\n", Mod(tot.mat[0][0] + tot.mat[0][1]));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/CH_Vaniteux/article/details/84978577