zoukankan      html  css  js  c++  java
  • [CF1182E] Product Oriented Recurrence

    [CF1182E] Product Oriented Recurrence - 矩阵快速幂

    Description

    (x geq 4) 时,(f_x = c^{2x - 6} cdot f_{x - 1} cdot f_{x - 2} cdot f_{x - 3}) 。现在已知 (n,f_1,f_2,f_3,c) 的值,求 (f_n) 的值,对 (10^9 + 7) 取模。((4 leq n leq 10^{18},1 leq f_1,f_2,f_3,c leq 10^9))

    Solution

    显然 (f_n=c^?f_1^?f_2^?f_3^?),指数显然是可以线性递推的,用矩阵快速幂优化即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    int n, f1, f2, f3, c;
    const int MOD = 1e9 + 7;
    const int mod = 1e9 + 6;
    
    struct Matrix
    {
        int n, m;
        int a[7][7];
    
        Matrix()
        {
            memset(a, 0, sizeof a);
        }
    
        int *operator[](int id)
        {
            return a[id];
        }
    
        Matrix operator*(const Matrix &rhs)
        {
            assert(m == rhs.n);
            Matrix res;
            res.n = n;
            res.m = rhs.m;
            for (int i = 1; i <= n; i++)
            {
                for (int j = 1; j <= rhs.m; j++)
                {
                    for (int k = 1; k <= m; k++)
                    {
                        res[i][j] += a[i][k] * rhs.a[k][j];
                        res[i][j] %= mod;
                    }
                }
            }
            return res;
        }
    };
    
    Matrix a0, a1, b0, b1, b2, b3;
    
    Matrix qpow(Matrix p, int q)
    {
        Matrix I;
        I.n = p.n;
        I.m = p.m;
        for (int i = 1; i <= I.n; i++)
            I[i][i] = 1;
        return (q & 1 ? p : I) * (q ? qpow(p * p, q / 2) : I);
    }
    
    const int eff[] = {1, 1, 1, 2, mod - 4, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 3, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0};
    
    void load()
    {
        int pos = 0;
        a0.n = a0.m = 5;
        for (int i = 1; i <= 5; i++)
            for (int j = 1; j <= 5; j++)
                a0[i][j] = eff[pos++];
        a1.n = a1.m = 3;
        for (int i = 1; i <= 3; i++)
            for (int j = 1; j <= 3; j++)
                a1[i][j] = eff[pos++];
        b0.n = 5;
        b0.m = 1;
        b1.n = 3;
        b1.m = 1;
        b2.n = 3;
        b2.m = 1;
        b3.n = 3;
        b3.m = 1;
        for (int i = 1; i <= 5; i++)
            b0[i][1] = eff[pos++];
        for (int i = 1; i <= 3; i++)
            b1[i][1] = eff[pos++];
        for (int i = 1; i <= 3; i++)
            b2[i][1] = eff[pos++];
        for (int i = 1; i <= 3; i++)
            b3[i][1] = eff[pos++];
    }
    
    int calc(int n, Matrix a, Matrix b)
    {
        n -= 3;
        Matrix c = qpow(a, n);
        Matrix d = c * b;
        return d[1][1];
    }
    
    int qpow(int p, int q)
    {
        return (q & 1 ? p : 1) * (q ? qpow(p * p % MOD, q / 2) : 1) % MOD;
    }
    
    int getf()
    {
        int qc = calc(n, a0, b0);
        int q1 = calc(n, a1, b1);
        int q2 = calc(n, a1, b2);
        int q3 = calc(n, a1, b3);
        return qpow(c, qc) * qpow(f1, q1) % MOD * qpow(f2, q2) % MOD * qpow(f3, q3) % MOD;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        load();
        cin >> n >> f1 >> f2 >> f3 >> c;
        cout << getf() << endl;
    }
    
  • 相关阅读:
    Android基础总结(四)网络通信
    Android基础总结(三)SQLite,ListView,对话框
    am335x sd卡启动系统参数设置
    am335x 电容屏驱动添加。
    linux 下恢复后台程序的方法
    qt-5.6.0 移植之实现板子与ubuntu主机通过网络进行文件传输
    qt-5.6.0 移植之qt文件系统的建立
    qt-5.6.0 移植之tslib 配置及编译
    qt-5.6.0 移植之qt源码编译
    qt-5.6.0 移植之纯净的linux文件系统的建立
  • 原文地址:https://www.cnblogs.com/mollnn/p/14647786.html
Copyright © 2011-2022 走看看