1. 程式人生 > >UVALive - 7501 Business Cycle (二分)

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