题解 Merchant
2021/8/10 6:35:36
本文主要是介绍题解 Merchant,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
传送门
可以发现如果我们最终选择的物品集合已经确定,就很好求了
\(\sum k*t+\sum b \geqslant s\) ,二分即可
但现在我们无法确定该选哪些物品
因此我们只需要check一下0时刻是否符合条件,如果不符合则进行二分。
注意check的时候我们只需要找出最大的 \(m\) 个即可
有点玄学。
证一下它有单调性:
因为保证有解,令存在一个解为时刻 \(t\)
那么此时存在一个 \(\sum k*t+\sum b \geqslant s\)
考虑时刻 \(t+1\),发现多了个 \(\sum k\)
若 \(\sum k > 0\) ,可以二分
若 \(\sum k \leqslant 0\) ,0时刻一定更优,不必二分
- 有空复习下nth_element的使用
Code:
#include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define N 1000010 #define ll long long #define reg register int //#define int long long char buf[1<<21], *p1=buf, *p2=buf; #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++) inline ll read() { ll ans=0, f=1; char c=getchar(); while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();} while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();} return ans*f; } int n, m; ll s; ll k[N], b[N]; const double eps=1e-8; namespace force{ ll ans=(ll)(1e18); void solve() { int lim=1<<n; double k1, b1, s1=s, t; for (reg s=1,s2,cnt; s<lim; ++s) { k1=0; b1=0; cnt=0; s2=s; do {s2&=(s2-1); ++cnt;} while (s2); if (cnt>m) continue; for (reg i=0; i<n; ++i) if (s&(1<<i)) k1+=k[i+1], b1+=b[i+1]; t=(s1-b1)/k1; //cout<<"t: "<<t<<' '<<bitset<5>(s)<<endl; if (ceil(t)>=-eps && k1*ceil(t)+b1>=s1-eps) ans=min(ans, (ll)ceil(t)); if (floor(t)>=-eps && k1*floor(t)+b1>=s1-eps) ans=min(ans, (ll)floor(t)); } printf("%lld\n", ans); exit(0); } } namespace task1{ ll tem[N]; inline bool cmp(ll a, ll b) {return a>b;} bool check(ll t) { for (reg i=1; i<=n; ++i) tem[i]=k[i]*t+b[i]; sort(tem+1, tem+n+1, cmp); ll sum=0; for (reg i=1; i<=m; ++i) if ((sum+=tem[i])>=s) return 1; return 0; } void solve() { ll l=0, r=(ll)(1e9), mid; while (l<=r) { mid=(l+r)>>1; if (!check(mid)) l=mid+1; else r=mid-1; } printf("%lld\n", l); exit(0); } } namespace task{ ll tem[N]; inline bool cmp(ll a, ll b) {return a>b;} bool check(ll t) { //cout<<"check "<<t<<endl; for (reg i=1; i<=n; ++i) tem[i]=k[i]*t+b[i]; nth_element(tem+1, tem+m, tem+n+1, cmp); //cout<<"tem: "; for (int i=1; i<=n; ++i) cout<<tem[i]<<' '; cout<<endl; ll sum=0; for (reg i=1; i<=m; ++i) if (tem[i]>0 && (sum+=tem[i])>=s) return 1; return 0; } void solve() { for (int i=1; i<=n; ++i) tem[i]=b[i]; sort(tem+1, tem+n+1, cmp); ll sum=0; for (reg i=1; i<=m; ++i) if ((sum+=tem[i])>=s) {puts("0"); exit(0);} ll l=0, r=(ll)(1e9), mid; while (l<=r) { mid=(l+r)>>1; if (!check(mid)) l=mid+1; else r=mid-1; } printf("%lld\n", l); exit(0); } } signed main() { bool geq=1, leq=1; n=read(); m=read(); s=read(); for (int i=1; i<=n; ++i) { k[i]=read(); b[i]=read(); if (b[i]>=s) {puts("0"); return 0;} if (k[i]>0) leq=0; else if (k[i]<0) geq=0; } //if (n<=20) force::solve(); //else if (geq) task1::solve(); //else if (leq) {puts("0"); return 0;} task::solve(); return 0; }
这篇关于题解 Merchant的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-27Rocket消息队列资料:新手入门指南
- 2024-11-27rocket消息队资料详解与入门指南
- 2024-11-27RocketMQ底层原理资料详解入门教程
- 2024-11-27RocketMQ项目开发资料:新手入门教程
- 2024-11-27RocketMQ项目开发资料详解
- 2024-11-27RocketMQ消息中间件资料入门教程
- 2024-11-27初学者指南:深入了解RocketMQ源码资料
- 2024-11-27Rocket消息队列学习入门指南
- 2024-11-26Rocket消息中间件教程:新手入门详解
- 2024-11-26RocketMQ项目开发教程:新手入门指南