UVALive - 7501 Business Cycle (二分)
解题思路:二分答案,重点在于判答案是否可行。我们先跑一遍,记录剩下的钱是多少,然后再跑一遍看看剩下的钱是多少。如果钱增加了,那么下次跑也一定增加。然后我们就可以通过这个差值,直接算出是否可行了。关于证明,要多画图。
另外这题会 爆LL,所以要特判
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
const long long INF=9e18+5;
int a[maxn];
int n;
long long g,p;
bool judge(long long u){
bool flag=false;
long long w=u;
long long v=p;
if (u>=g) return true;
for (int i=1;i<=n;i++){
w+=a[i];
v--;
if (w<0)
w=0;
if (w>=g) return true;
if (v==0) return false;
}
if (w<=u) return false;
long long k=w;
for (int i=1;i<=n;i++){
w+=a[i];
v--;
if (w<0)
w=0;
if (w>=g) return true;
if (v==0) return false;
}
if (w<=k) return false;
long long num=w-k;
long long cong2=v/n;
v=v%n+n;
if (cong2==0) v-=n;
else if (cong2-1>INF/num) w=INF;
else w+=num*(cong2-1);
if (w>=g) return true;
for (int i=1;i<=n;i++){
w+=a[i];
v--;
if (w<0)
w=0;
if (w>=g) return true;
if (v==0) return false;
}
if (w>=g) return true;
for (int i=1;i<=n;i++){
w+=a[i];
v--;
if (w<0)
w=0;
if (w>=g) return true;
if (v==0) return false;
}
}
int main(){
int T,Case=0;
cin >> T;
while (T--){
Case++;
scanf("%d%lld%lld",&n,&g,&p);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
long long l=0,r=g;
while (l<=r){
long long mid=(l+r)>>1;
if (judge(mid)) r=mid-1;
else l=mid+1;
}
printf("Case #%d: %lld\n",Case,l);
}
}/*5
21 388560582839343128 485024093467834189
-70314576 -84954814 -78349477 80179248 -250850463 -38409317 88095409 -132974204 163257708 260479047 86272785 248884731 -62998186 -136531433 -22617961 -256537759 -265731338 -257977770 -127232207 76068196 248209093
*/