• HDU


    除去常数,就是一个广义斐波那契数列,加上常数,就是把原来的二维矩阵变成三维矩阵
    但是常数是在变化的,而利用整除分块的思想发现,在同一块的(frac{p}{i})是相同的。所以只需要维护两个值,(fn_1)表示该分块的第一个元素的前面第一个值,(fn_2)表示该分块的第一个元素的前面第二个值。
    整除分块的左区间从3开始就行了,利用矩阵快速幂及时更新(fn_1)(fn_2)即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define ll long long
    using namespace std;
    const int mod = 1e9 + 7;
    const int N = 3;
    struct Matrix{
        int n, m;
        ll a[N][N];
        Matrix(int n = 0, int m = 0):n(n),m(m){memset(a, 0, sizeof(a));};
        Matrix operator * (const Matrix &b) const {
            Matrix ans(n, b.m);
            for(int i = 0; i < n; i++) {
                for(int j = 0; j < b.m; j++) {
                    for(int k = 0; k < m; k++) {
                        ans.a[i][j] = (ans.a[i][j] + a[i][k] * b.a[k][j] % mod) % mod;
                    }
                }
            }
            return ans;
        }
    };
    Matrix ksm(Matrix a, ll b){
        Matrix ans(a.n, a.m);
        for(int i = 0; i < max(a.n, a.m); i++) ans.a[i][i] = 1;
        while(b){
            if(b & 1) ans = ans * a;
            a = a * a;
            b >>= 1;
        }
        return ans;
    }
    ll a, b, c, d;
    ll F(ll n, ll fn_1, ll fn_2, ll C_3) {
        Matrix base(3, 3);
        base.a[0][0] = d, base.a[0][1] = c, base.a[0][2] = 1;
        base.a[1][0] = 1;
        base.a[2][2] = 1;
        base = ksm(base, n - 2);
        Matrix ans(3, 1);
        ans.a[0][0] = fn_1;
        ans.a[1][0] = fn_2;
        ans.a[2][0] = C_3;
        ans = base * ans;
        return ans.a[0][0];
    }
    ll cal(ll n, ll p){ // fn_1 = fn - 1
        if(n == 1) return a;
        ll fn_1 = b, fn_2 = a, C_3 = p / 3;
        for(ll l = 3, r; l <= n; l = r + 1) {
            r = p / l ? min(p / (p / l), n) : n;
            C_3 = p / l;
            ll nowfn_1 = F(r - (l - 3), fn_1, fn_2, C_3);
            ll nowfn_2 = F(r - 1 - (l - 3), fn_1, fn_2, C_3);
            fn_1 = nowfn_1; fn_2 = nowfn_2;
        }
        return fn_1;
    }
    void solve(){
        ll n, p;
        scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
        scanf("%lld%lld", &p, &n);
        printf("%lld
    ", cal(n, p));
    }  
    int main(){
        int t;
        scanf("%d", &t);
        while(t--) solve();
        return 0;
    }
    
  • 相关阅读:
    0x01 虚拟环境搭建
    python操作mysql8windows环境
    Navicat 导入sql文件执行失败问题的处理
    mysql8.0.16免安装教程
    zend studio 9.0.3 注册码
    oneplus8手机蓝牙连接tws耳机无法双击退出语音助手
    竞品分析
    源码阅读方法
    Tomcat内核1
    Asp.NetCore3.1开源项目升级为.Net6.0
  • 原文地址:https://www.cnblogs.com/Emcikem/p/13879435.html
Copyright © 2020-2023  润新知