CF889E Mod Mod Mod 题解

题目传送门 洛谷题目传送门

思路

首先可以想到, x = a i − 1 x=a_i-1 x=ai1 中肯定是存在最优解的。那么考虑 dp。

d p i , j dp_{i,j} dpi,j 表示第 i i i 个数, x x x j j j 的最大值,分两种情况:

  1. j < a i j<a_i j<ai d p i , j = d p i − 1 , j dp_{i,j}=dp_{i-1,j} dpi,j=dpi1,j,即可以直接转移;
  2. j ≥ a i j\ge a_i jai:分两种转移:
    • x x x 变为 a x − 1 a_x-1 ax1,则 d p i , a i − 1 = d p i − 1 , j + ( i − 1 ) × ( ⌊ j + 1 a i ⌋ × a i − a i ) dp_{i,a_i-1}=dp_{i-1,j}+(i-1)\times(\lfloor\frac{j+1}{a_i}\rfloor\times a_i-a_i) dpi,ai1=dpi1,j+(i1)×(⌊aij+1×aiai)
    • 就取当前的值,则 d p i , j   m o d   a i = d p i , j + ( i − 1 ) × ( j − j   m o d   a i ) dp_{i,j\bmod a_i}=dp_{i,j}+(i-1)\times(j-j\bmod a_i) dpi,jmodai=dpi,j+(i1)×(jjmodai)

由于值域比较大,所以直接开个 map 来维护 d p dp dp 数组,再继续优化空间,用滚动数组的思想。时间复杂度为 O ( n log ⁡ n log ⁡ V ) O(n\log n\log V) O(nlognlogV) V V V 为值域)。

代码

#include <bits/stdc++.h>
#define int long long
#define x first
#define y second
using namespace std;
const int N = 2e5+5;
int n,a[N],ans;
map<int,int> dp;
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i = 1;i<=n;i++)
		cin>>a[i];
	dp[a[1]-1] = 0;
	for(int i = 2;i<=n;i++)
	{
		for(auto j = dp.lower_bound(a[i]);j!=dp.end();dp.erase(j++))
		{
			int x = j->x,y = j->y;
			dp[x%a[i]] = max(dp[x%a[i]],y+(i-1)*(x-x%a[i]));
			dp[a[i]-1] = max(dp[a[i]-1],y+(i-1)*((x+1)/a[i]*a[i]-a[i]));
		}
	}
	for(auto i = dp.begin();i!=dp.end();i++)
	{
		int x = i->x,y = i->y;
		ans = max(ans,x*n+y);
	}
	cout<<ans;
	return 0;
}
  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值