题解:AT_abc389_e [ABC389E] Square Price
1.题解:P9923 [POI 2023/2024 R1] Przyciski2.题解:P6544 [CEOI2014] Cake3.题解:CF690A2 Collective Mindsets (medium)4.题解:AT_arc050_c [ARC050C] LCM 1115.题解:P11311 漫长的小纸带6.题解:CF815D Karen and Cards
7.题解:AT_abc389_e [ABC389E] Square Price
8.题解:P11490 [BalticOI 2023] Staring Contest9.题解:[ABC355E] Guess the Sum10.题解:AT_abc283_g [ABC283G] Partial Xor Enumeration11.题解:P2540 [NOIP2015 提高组] 斗地主 加强版12.题解:AT_abc373_g [ABC373G] No Cross Matching13.题解:P4026 [SHOI2008] 循环的债务14.题解:P11644 【MX-X8-T3】「TAOI-3」地地爱打卡15.题解:P11617 递推16.题解:[AGC054D] (ox)17.题解:Minimize Inversions Number18.题解:Many Many Cycles19.CF Round 1001 题解合集20.题解:The Game (Easy Version & Hard Version)21.abc391 题解合集22.题解:[AGC044D] Guess the Password23.题解:Coprime Permutation24.题解:[THUPC 2021] 鬼街25.题解:P8393 [BalticOI 2022] Stranded Far From Home (Day2)26.题解:P9989 [Ynoi Easy Round 2023] TEST_6927.题解:mex times mex(省选模拟赛 T2)28.abc392 题解合集29.S2OJ 20250211 题解合集30.CF Round 1004 题解合集31.CF Round 1002 题解合集32.abc393 题解合集33.CF Round 1005 题解合集34.CF Round 997 题解合集35.CF Round 999 题解合集36.CF Round 998 题解合集37.CF Edu Round 174 题解合集38.2025 USACO Feb 银组题解合集39.S2OJ 20250223 题解合集前言
E 比 F 困难,怎么会是呢?
思路分析
首先考虑一种经典做法:将问题转化为物品体积为 的 01 背包问题。因为物品价值都为 ,所以可以贪心地选择体积前 小的物品。
然后问题转化到这一步就自然了,考虑二分出我们选与不选的物品体积的临界值,小于等于这个值的物品都选上。
已知临界值 ,对于每一个 ,我们选择的物品数量 应该满足:
放缩一下:
这里有一个细节:在选完小于等于临界值的物品后,如果背包容量还有剩余,会考虑选择大于临界值的物品,特判一下即可。
总体复杂度 。
代码实现
不知道在 check 时会不会炸 long long,所以开了 __int128。
#include<bits/stdc++.h>
using namespace std;
long long ans,p[200005],sum,m,n,maxn;
bool check(long long ans){
__int128 sum=0;
for(int i=1;i<=n;i++){
__int128 num=((ans/p[i]+1))/2;
sum+=num*num*p[i];
if(sum>m) return false;
}
return true;
}
long long find(long long l,long long r){
if(l==r) return l;
long long mid=(l+r+1)>>1;
if(check(mid)) return find(mid,r);
else return find(l,mid-1);
}
int main(){
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(long long i=1;i<=n;i++){
cin>>p[i];
}
ans=find(0,m);
for(long long i=1;i<=n;i++){
__int128 num=(ans/p[i]+1)/2;
sum+=num;
m-=num*num*p[i];
maxn=max((__int128)maxn,(2*num+1)*p[i]);
}
sum+=m/maxn;
cout<<sum;
return 0;
}
本文作者:Kenma
本文链接:https://www.cnblogs.com/Kenma/p/18689777
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步