1 条题解

  • 0
    @ 2021-11-19 9:07:15

    首先考虑只有两个数 a,ba,b 的情况。

    aa 需要通过分裂来小于等于 bb,最优策略是平均分,设平均分为 kk 份。

    则最右边的是 ak\lceil \frac{a}{k}\rceil ,最左边的是 ak\lfloor \frac{a}{k}\rfloor

    k=akk=\lfloor \frac{a}{k}\rfloor​ 时,满足条件且最优。

    可以从后向前确定每一个数的答案。

    由于 ak\lfloor\frac{a}{k}\rfloor 只有 a\sqrt a 种取值,所以直接暴力存转移即可。

    时间复杂度 O(nn)O(n\sqrt n)


    代码
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5,mod=998244353;
    int _,n,a[N];
    vector<pair<int,int> > f,g;
    int ceil(int a,int b){return (a+b-1)/b;}
    int main() {
        scanf("%d",&_);
        while(_--){
            int ans=0;
            scanf("%d",&n);
            for(int i=1;i<=n;i++)scanf("%d",&a[i]);
            f.clear();
            g.clear();
            for(int i=n;i>=1;i--){
                for(auto pi:f){
                    int k=ceil(a[i],pi.first);
                    ans=(ans+1ll*(k-1)*pi.second%mod*i%mod)%mod;//本次操作需要k-1次,前面还有i个左端点需要统计这个答案
                    if(a[i]/k==g.back().first)g.back().second+=pi.second;//由于保证了vector中有序,所以不需要排序
                    else g.push_back(make_pair(a[i]/k,pi.second));
                }
                g.push_back(make_pair(a[i],1));
                f=g;
                g.clear();
            }
            printf("%d\n",ans);
        }
        return 0;
    }
    
    • 1

    信息

    ID
    15
    时间
    4000ms
    内存
    256MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者