【luogu CF889E】Mod Mod Mod(性质)(DP)

Mod Mod Mod

题目链接:luogu CF889E

题目大意

f(x,n)=1
f(x,i)=(xmodai)+f(xmodai,i+1)
然后给你数组 a,要你找到一个 x 使得 f(x,1) 最大,输出这个 f(x,1) 即可。

思路

首先有一个很神奇的东西就是一定会有一个数组中的数 ai 到它的贡献是 ai1(否则你可以把这个数变大 1,所以位置的贡献都 +1

然后设 fi,j 为前 i 个数组搞定了,然后当前是 j 的取模漏了的贡献(也就是一个位置贡献是 ij+fi,j

然后有一个东西是 fi,j=max{fi,k}(kj)

那有用的状态似乎就只有 n2 个了。
(就小于的位置不用,模了有变化的就模)
(或者让这个位置作为 ai1 的位置,然后你就在大于的时候枚举一下,让 fi,j 作为做的值)

但其实是 nlogn 个状态的,因为你取模每个数最多取 log 个就没了。
然后用 map 记录当前状态即可。

代码

#include<map> #include<cstdio> #include<algorithm> #define ll long long using namespace std; const int N = 2e5 + 100; ll n, x; map <ll, ll> f; int main() { scanf("%lld", &n); for (int i = 1; i <= n; i++) { scanf("%lld", &x); if (i == 1) f[x - 1] = 0; else { for (map <ll, ll> ::iterator it = f.lower_bound(x); it != f.end(); f.erase(it++)) { ll now = (*it).first, val = (*it).second; f[now % x] = max(f[now % x], val + (i - 1) * (now - now % x)); f[x - 1] = max(f[x - 1], val + (i - 1) * (((now + 1) / x * x - 1) - (x - 1))); } } } ll ans = 0; for (map <ll, ll> ::iterator it = f.begin(); it != f.end(); it++) ans = max(ans, n * (*it).first + (*it).second); printf("%lld", ans); return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/luogu_CF889E.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示