CF889E Mod Mod Mod

http://codeforces.com/problemset/problem/889/E

题解

首先我们观察到在每次取模的过程中一定会有一次的结果是\(a_i-1\),因为如果不是,我们可以调整,答案肯定是会更优的。

于是我们的有用状态就变成了\(O(n)\)级别。

我们可以对于一个状态,把它表示为\((a,b)\),表示前\(i\)个数,当前取完模的结果为\(a\),总和写成\(i*a+b\)的形式后最大的\(b\)

我们的转移每次要把\(a\)变成\(a%v\),再添加一个新状态\(v-1\)

转移讨论一下。

代码

#include<bits/stdc++.h>
#define N 200009
using namespace std;
typedef long long ll;
const int mod=1e9+7;
map<ll,ll>f;
map<ll,ll>::iterator it;
int n;
inline ll rd(){
    ll x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
int main(){
    n=rd();
    f[rd()-1]=0;
    for(int i=2;i<=n;++i){
        ll x=rd();
        while(!f.empty()){
            it=f.end();--it;
            ll a=it->first,b=it->second;
            if(a<x)break; 
            f.erase(it);
            f[x-1]=max(f[x-1],b+1ll*(i-1)*(a-a%x-x));
            f[a%x]=max(f[a%x],b+1ll*(i-1)*(a-a%x));
        }
    }
    ll ans=0;
    for(it=f.begin();it!=f.end();++it)ans=max(ans,it->first*n+it->second);
    cout<<ans;
    return 0;
}
posted @ 2019-06-14 07:55  comld  阅读(331)  评论(0编辑  收藏  举报