• Codeforces 837F


    837F - Prefix Sums

    题意

    定义函数 (p(x)) 会返回 (x) 这个数组的前缀和,定义 (A^i=p(A^{i-1}) (i > 0)),给出 (A^0) 求使得 (A^i) 中存在大于等于 (k) 的数的最小的 (i)

    分析

    打表容易发现当数的数量大于 (4) 时,直接暴力就很快。

    关键就是数量有 (2)(3) 个时,怎么快速计算答案。

    模拟一下发现,存在递推关系:

    即第 (0) 项矩阵为

    [egin{bmatrix} a_1 & a_2 & a_3 end{bmatrix} ]

    那么第一项的矩阵为

    [egin{bmatrix} a_1 & a_2 & a_3 end{bmatrix} * egin{bmatrix} 1 & 1 & 1\ 0 & 1 & 1\ 0 & 0 & 1 end{bmatrix}=egin{bmatrix} a_1 & a_1+a_2 & a_1+a_2+a_3 end{bmatrix} ]

    后面类似,又显然存在单调性,可以使用二分求解。

    这道题比较坑的就是会超 (long long) ,用了 (long double) 才能过,这种做法坑点有点多。

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 2e5 + 10;
    const int N = 10;
    typedef long long ll;
    ll a[MAXN];
    int n, cnt = 0;
    ll K;
    struct Matrix {
        long double mat[N][N];
        void init() {
            for(int i = 0; i < cnt; i++) {
                for(int j = 0; j < cnt; j++) {
                    mat[i][j] = 0;
                }
            }
        }
    };
    Matrix operator * (Matrix A, Matrix B) {
        Matrix C;
        C.init();
        for(int i = 0; i < cnt; i++) {
            for(int j = 0; j < cnt; j++) {
                for(int k = 0; k < cnt; k++) {
                    C.mat[i][j] += A.mat[i][k] * B.mat[k][j];
                }
            }
        }
        return C;
    }
    Matrix operator ^ (Matrix A, ll x) {
        Matrix B;
        B.init();
        for(int i = 0; i < cnt; i++) {
            for(int j = 0; j < cnt; j++) {
                if(i == j) B.mat[i][j] = 1;
            }
        }
        while(x) {
            if(x & 1) B = B * A;
            A = A * A;
            x >>= 1;
        }
        return B;
    }
    int judge(ll x) {
        Matrix A;
        A.init();
        for(int i = 0; i < cnt; i++) {
            for(int j = i; j < cnt; j++) {
                A.mat[i][j] = 1;
            }
        }
        A = A ^ x;
        Matrix B;
        B.init();
        for(int i = 0; i < cnt; i++) B.mat[0][i] = a[i + 1];
        B = B * A;
        for(int i = 0; i < cnt; i++) {
            if(B.mat[0][i] >= K) return 1;
        }
        return 0;
    }
    int main() {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cin >> n >> K;
        for(int i = 0; i < n; i++) {
            ll x;
            cin >> x;
            if(!cnt && !x) continue;
            if(x >= 0) { a[++cnt] = x; }
            if(x >= K) {
                K = 0;
            }
        }
        ll ans = 0;
        if(K && cnt >= 4) {
            int flr = 1;
            while(1) {
                for(int i = 1; i <= cnt; i++) {
                    a[i] += a[i - 1];
                    if(a[i] >= K) {
                        ans = flr;
                        break;
                    }
                }
                if(ans) break;
                flr++;
            }
        } else if(K) {
            ll l = 0, r = K;
            while(l < r) {
                ll mid = (l + r) / 2;
                if(judge(mid)) r = mid;
                else l = mid + 1;
            }
            ans = l;
        }
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    【转】Spring Boot run方法执行流程
    自定义Google扩展皮肤
    vscode定制注释为斜体样式
    2022年·阅读·离散数学&数据结构
    2022年·阅读
    今天发现rutracker放开了注册入口
    重置 Windows安全中心
    数据结构之堆 → 不要局限于堆排序
    心跳包设计
    react js—— annotation (注释) in renders
  • 原文地址:https://www.cnblogs.com/ftae/p/7360444.html
Copyright © 2020-2023  润新知