求调ABC E
  • 板块题目总版
  • 楼主liyixin0514
  • 当前回复0
  • 已保存回复0
  • 发布时间2025/1/18 21:44
  • 上次更新2025/1/19 09:46:34
查看原帖
求调ABC E
542128
liyixin0514楼主2025/1/18 21:44

思路是贪心地选择单价低的物品。二分物品单价上限,checkcheck 判断每种物品选择最多的数量,使得单价不超过上限,总花费是否合法。

最后再判断每种物品有没有可能数量再多一个,使得总花费仍然合法。

楼主可能晚一点再上线,先下线了,见谅。

提前拜谢大佬orz

#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
namespace gigantic {
	constexpr int N=2e5+7;
	int n;
	ll m;
	int p[N];
	ll l,r;
	ll check(ll lim) {
		ll sum=0;
		ll cnt=0;
		int it=1;
		while(sum<=m && it<=n) {
			ll s=(lim/p[it]-1)/2+1;
			cnt+=s;
			sum+=s*s*p[it];
			++it;
			// if(lim==44) pf("cnt = %lld\n",cnt);
		}
		if(sum<=m) return cnt;
		return -1;
	}
	ll x;
	ll ans;
	ll c[N];
    void main() {
		sf("%d%lld",&n,&m);
		rep(i,1,n) sf("%d",&p[i]);
		l=0,r=m;
		while(l<r) {
			ll mid=(l+r+1)>>1;
			// pf("mid = %lld\n",mid);
			x=check(mid);
			if(x!=-1) l=mid, ans=x;
			else r=mid-1;
		}
		ans=0;
		ll sum=0;
		rep(it,1,n) {
			ll s=(l/p[it]-1)/2+1;
			ans+=s;
			c[it]=s;
			sum+=s*s*p[it];
		}
		vector<int> vec;
		rep(i,1,n) {
			vec.push_back((2ll*c[i]+1)*p[i]);
		}
		sort(vec.begin(),vec.end());
		for(ll cost : vec) {
			if(cost+sum<=m) ++ans,sum+=cost;
			else break;
		}
		// pf("l = %lld\n",l);
		pf("%lld\n",ans);
    }
}
int main() {
    #ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("my.out","w",stdout);
    #endif
    gigantic :: main();
}
2025/1/18 21:44
加载中...