【DP】Mod Mod Mod(CF889E)
正題
CF889E
luogu
題目大意
給你 n 個數,讓你選擇一個X,使得 ∑i=1nXmoda1moda2...modai\sum_{i=1}^nX\mod a_1\mod a_2...\mod a_i∑i=1n?Xmoda1?moda2?...modai? 最大
解題思路
可以發現必定存在一個 i ,使得當前點貢獻為 aia_iai?,否則把 X 加一顯然可以得到更優的答案
樸素的狀態轉移很難優化,考慮令 fi,jf_{i,j}fi,j? 表示到第 i 個點,當前值為 0~j0\sim j0~j,當前總貢獻為 i×(0~j)+fi,ji\times (0\sim j)+f_{i,j}i×(0~j)+fi,j?,即把 j 個狀態存到了一起,然后把模后的貢獻存在 f 中
對于 ai+1>ja_{i+1}>jai+1?>j,直接傳遞即可
否則存在兩種轉移
fi+1,jmodai+1=max(fi,j+i×(j?jmodai+1)fi+1,ai+1?1=max(fi,j+i×(((j+1)/ai+1×ai+1?1)?(ai+1?1))f_{i+1,j\mod a_{i+1}}=max(f_{i,j}+i\times (j-j\mod a_{i+1}) \\ f_{i+1,a_{i+1}-1}=max(f_{i,j}+i\times(((j+1)/a_{i+1}\times a_{i+1}-1)-(a_{i+1}-1)) fi+1,jmodai+1??=max(fi,j?+i×(j?jmodai+1?)fi+1,ai+1??1?=max(fi,j?+i×(((j+1)/ai+1?×ai+1??1)?(ai+1??1))
第二個轉移即找到最大的值使其轉移到 ai+1?1a_{i+1}-1ai+1??1
因為一個數模了之后至少減半,所以最多轉移 logxlog\ xlog?x次
時間復雜度 O(nlognlogx)O(nlog\ n\ log\ x)O(nlog?n?log?x)
code
#include<map> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long using namespace std; map<ll,ll>::iterator it; ll n,x,y,z,ans; 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(it=f.lower_bound(x);it!=f.end();f.erase(it++)){y=(*it).first;z=(*it).second;f[y%x]=max(f[y%x],z+(i-1)*(y-y%x));f[x-1]=max(f[x-1],z+(i-1)*((y+1)/x*x-x));}}}for(it=f.begin();it!=f.end();it++)ans=max(ans,(*it).first*n+(*it).second);printf("%lld",ans);return 0; }總結
以上是生活随笔為你收集整理的【DP】Mod Mod Mod(CF889E)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 徐少强的电视剧有哪些
- 下一篇: 【平衡规划】Arithmetic Ope