E. Mod Mod Mod
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given a sequence of integers a1, a2, …, an. Let , and for 1 ≤ i < n. Here, denotes the modulus operation. Find the maximum value of f(x, 1) over all nonnegative integers x.
Input
The first line contains a single integer n (1 ≤ n ≤ 200000) — the length of the sequence.
The second lines contains n integers a1, a2, …, an (1 ≤ ai ≤ 1013) — the elements of the sequence.
Output
Output a single integer — the maximum value of f(x, 1) over all nonnegative integers x.
Examples
input
2
10 5
output
13
input
5
5 4 3 2 1
output
6
input
4
5 10 5 10
output
16
题意:给出n个数,对于任意的x,第i为的贡献为x%num[1]%num[2],,,%num[i],问每一位的贡献和最大是多少。
做法:我就翻译一下题解好了
1:设ansi 代表第1位到第i位的贡献和,然后定义一个三元组,i,r,k.对于第i位当他取值范围是0,r时,可以用ansi=ax*i+k(0<=ax<=r)表示,那么对于每个三元组,可以往第i+1为传递两个三元组,(i,r,k)可以往后面传递两个(i+1,r%num[i+1],k+i*(r-r%mod))和(i+1,num[i+1]-1,k+i*(r-r%modnum[i+1]-num[i+1])),这两个三元组,原因么,因为第i为可以用这个三元组表示,那么对于这个三元组,当第i+1个数取值在0到r%num[i+1]时,第i个数可以取值为这个数加上r/mod*mod,这样是最优,而当大于等于r%num[i+1],就要再减去一个num[i+1]。原因自己模拟一下,这样最多有2^n中三元组,然后如果用dp[i][r]=k保存i,r状态下最大的k,这样最大的复杂度是n*n,因为对于第i为来说最多只会有i个r,假设第i为只有i个r,那么到第i+1位,最多只会多一个num[i+1]-1,因为对于大于等于num[i+1]的r,会被取余,小于的不会变。所以说每一位最多比前一位多1,所以是n*n的复杂度,然后还可优化一下,前面提到了,当从i转移到i+1的时候小于num[i+1]的r的dp值是可以保持不变的,因为通过上面那个式子可以发现是不会变大的,一个数最多经过log次取模比它小的数就会变成0,所以用map保存当前的r,然后每次找出比num[i]大的数,取模然后把这个数从map中拿掉,因为每个数最多会被拿出log次,所以复杂度是n*log(1e13)*log(n);
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5+100;
map<ll,ll> mp;
int n;
ll num[N];
int main(){
cin >> n;
for(int i = 1;i <= n;i ++) scanf("%lld",&num[i]);
mp[num[1]-1] = 0;
for(int i = 1;i <= n;i ++){
while(1){
auto it = mp.lower_bound(num[i]);
if(it == mp.end() || (*it).first < num[i]) break;
//cout <<(*it).first << endl;
ll a= (*it).first,b = (*it).second;
mp.erase(it);
ll nex = a%num[i];
mp[nex] = max(mp[nex],b+(i-1)*(a-a%num[i]));
mp[num[i]-1] = max(mp[num[i]-1],b+(i-1)*(a-a%num[i]-num[i]));
}
}
ll ans = 0;
for(auto it : mp){
ans = max(ans,it.first*n+it.second);
//cout <<it.first << ' '<< it.second<< endl;
}
cout << ans << endl;
return 0;
}