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
*/

 

 

 

 

发布了402 篇原创文章 · 获赞 67 · 访问量 16万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 点我我会动 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览