CF889E

题目大意: 给出正整数 n 和序列 {Ai} ,定义 fk(x)=fk1(x)modak,f0(x)=x ,求 maxxi=1nfk(x)
n2105,Ai1013.

首先容易发现答案的 x 一定是某个 Ai1
这就可以 n2 做了。

然后尝试把 n2 用 DP 做,设 fi,j 为做到第 i 项,fi(x)=j 的答案。
发现所有转移都是有意义转移,不好搞。
考虑 x<ai 的时候,贡献都是一样的,所以把贡献变为 ifi(x)+b 的形式,此时 j<ai 就不需要转移了。
分析取模的过程发现 x 每次“有效取模”后至多是原本的一半。
因此只会有 O(logA) 次转移发生于此。

做完了。复杂度 O(nlogAlogn)

#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,d) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
const int N=2e5+10;
int n,m;
ll a[N];
map<ll,ll> f;
void trans(ll &a,ll b){a=(a>b?a:b);}
int main(){
	scanf("%d",&n);
	fo(i,1,n)scanf("%lld",&a[i]);
	f[a[1]-1]=0;
	fo(i,2,n){
		for(map<ll,ll>::iterator it=f.lower_bound(a[i]);it!=f.end();++it){
			trans(f[it->first % a[i]] , it->second + (ll)(i-1)*(it->first-it->first%a[i]));
			if(it->first>=a[i])trans(f[a[i]-1] , it->second + (ll)(i-1)*(it->first - it->first % a[i] -1 - (a[i]-1)));
		}
		f.erase(f.lower_bound(a[i]),f.end());
	}
	ll ans=0;
	for(auto it:f){
		trans(ans , it.second + it.first*n);
	}
	printf("%lld\n",ans);

	return 0;
}
posted @   Kelvin2005  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
历史上的今天:
2021-11-18 记:关于费马平方和定理的证明
点击右上角即可分享
微信分享提示