zoukankan      html  css  js  c++  java
  • AcDream 1078 递推数 嵌套循环节+矩阵快速幂

    题意:已知A0 = 0 , A1 = 1 , An = 3 * An - 1 + An - 2 (n >= 2). 求 AAAAN Mod (1e9 + 7) (也就是A[A[A[A[N]]]])。

    解法:标程竟然使用set+pair来寻找循环节,并且第一次循环节长达222222224,不知道内存要吃掉多少。由于是一个嵌套的定义,因此要找出每一层的循环节,最终推出最内层的循环节为240,次之为183120,再之222222224,最后就是1e9+7了。通过矩阵快速幂求解第x项还是飞快的,注意当某一层为0时最后的结果就为0了。

    代码如下:

    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    typedef long long int int64;
    const int mod[4] = {240, 183120, 222222224, 1000000007};
    int MOD;
    
    struct Matrix {
        int64 mat[2][2];
        void reset() {
            mat[0][0] = 3, mat[1][0] = 1;
            mat[0][1] = 1, mat[1][1] = 0;
        }
        void unit() {
            mat[0][0] = 1, mat[1][0] = 0;
            mat[0][1] = 0, mat[1][1] = 1;
        }
        void init() {
            memset(mat, 0, sizeof (mat));
        }
        friend int64 pow(Matrix & a, int b);
        friend Matrix operator * (const Matrix & a, const Matrix & b);
    };
    
    int64 pow(Matrix & a, int64 b) {
        Matrix ret;
        ret.unit();
        while (b) {
            if (b & 1) ret = ret * a;
            a = a * a;
            b >>= 1;
        }
        return ret.mat[0][0];
    }
    
    Matrix operator * (const Matrix & a, const Matrix & b) {
        Matrix ret;
        ret.init();
        for (int i = 0; i < 2; ++i)
        for (int j = 0; j < 2; ++j)
        for (int k = 0; k < 2; ++k) {
            ret.mat[i][j] += (a.mat[i][k] * b.mat[k][j]) % MOD;
            ret.mat[i][j] %= MOD;
        }
        return ret;
    }
    
    void solve(int64 x) {
        for (int i = 0; i < 4; ++i) {
            Matrix mm;
            mm.reset();
            MOD = mod[i];
            if (x > 0) { 
                x = pow(mm, x-1);
            } else x = 0;
        }
        printf("%lld\n", x);
    }
    
    int main() {
        int T;
        int64 N;
        scanf("%d", &T);
        while (T--) {
            scanf("%lld", &N);
            solve(N);
        }
        return 0;    
    }
  • 相关阅读:
    web----WSGI
    ovs 实现vlan隔离(一)
    ovs流表机制(四)用vxlan实现不同网段通信
    ovs流表机制(四)用vxlan实现同网段通信
    ovs 流表机制(三)--group表
    ovs 流表机制(二)-OVS流表table之间的跳转
    ovs 流表机制(一)
    euler ironic镜像驱动问题(一)镜像启动失败报dracut initqueue timeout
    ovs流表
    arm64 uefi启动
  • 原文地址:https://www.cnblogs.com/Lyush/p/2971743.html
Copyright © 2011-2022 走看看