UVALive 7501 Business Cycle(二分)题解
题意:n个数,有一个起始值,按顺序从第一个开始不断循环取数,如果取完后相加小于0就变为0,最多取p个数,问你得到大于等于值g所需要的最小起始值为多少
思路:这题目爆long long爆的毫无准备,到处都有可能爆值。
显然,我们能想出,初始值越大,那么走相同步数所得到的数字就会越大(或相等),那么我们就可以用二分法每次判断是否能得到g值,大概logG * n * C的复杂度。那么现在问题就是怎么判定初始值s是否能得到g值。
我们可以求循环两次的结果差dis = tot2 - tot1,来判断每次循环的走向是增还是减或者不变。之所以算两次循环是因为可能遇到这样的样例:
4 5 10
1 2 -100 20
假设我初始值为10,那么第一次循环后得到20,那么其实不是一次循环就会增长10,因为第二次循环后还是20,所以要循环两次判断走势。
p <= 2n 或者 dis <= 0直接遍历两次循环就行了; p > 2n时,我们就让他一直循环,然后遍历最后一圈+ mod(就是p % n)。为什么不是只遍历最后的mod,而是要提前一圈遍历?因为有可能我在最后一圈里可能遇到在最后几个数中出现了-INF的超小值,我吃了这个超小值之后就不划算了。
最后注意别随时有可能爆long long...orz
代码:
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxn = 1e5 + ;
const int MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
ll v[maxn];
ll n, g, p;
bool getMax(ll st){
if(st >= g) return true;
if(p <= n){
ll tot = st;
for(ll i = ; i < p; i++){
tot += v[i];
if(tot < ) tot = ;
if(tot >= g) return true;
}
return false;
}
else{ //p > n
ll tot = st;
for(ll i = ; i < n; i++){
tot += v[i];
if(tot < ) tot = ;
if(tot >= g) return true;
}
ll last = tot;
if(p <= * n){
for(ll i = ; i < p - n; i++){
tot += v[i];
if(tot < ) tot = ;
if(tot >= g) return true;
}
return false;
}
else{ //p > 2n
for(ll i = ; i < n; i++){
tot += v[i];
if(tot < ) tot = ;
if(tot >= g) return true;
}
ll dis = tot - last;
if(dis <= ) return false;
else{
ll k = p / n, rest;
k--;
if(k >= g / dis) return true; //防止爆long long
rest = p - k * n;
tot = last + dis * (k - 1LL);
if(tot >= g) return true;
for(ll i = ; i < n; i++){
tot += v[i];
if(tot < ) tot = ;
if(tot >= g) return true;
}
rest -= n;
for(ll i = ; i < rest; i++){
tot += v[i];
if(tot < ) tot = ;
if(tot >= g) return true;
}
return false;
}
}
}
}
int main(){
int t, ca = ;
scanf("%d", &t);
while(t--){
scanf("%lld%lld%lld", &n, &g, &p);
for(ll i = ; i < n; i++){
scanf("%lld", &v[i]);
}
ll l = , r = g, ans = g;
while(l <= r){
ll m = (l + r) / ;
if(getMax(m)){
r = m - ;
ans = m;
}
else{
l = m + ;
}
}
printf("Case #%d: %lld\n", ca++, ans);
}
return ;
}
UVALive 7501 Business Cycle(二分)题解的更多相关文章
- UVALive 7501 Business Cycle
细心题 #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) # ...
- UVALive - 3211 (2-SAT + 二分)
layout: post title: 训练指南 UVALive - 3211 (2-SAT + 二分) author: "luowentaoaa" catalog: true m ...
- UVALive 3971 Assemble(模拟 + 二分)
UVALive 3971 题意:有b块钱.想要组装一台电脑,给出n个配件的种类,名字,价格,品质因子.若各种类配件各买一个,总价格<=b,求最差品质配件的最大品质因子. 思路: 求最大的最小值一 ...
- poj 1064 Cable master 二分 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=1064 题解 二分即可 其实 对于输入与精度计算不是很在行 老是被卡精度 后来学习了一个函数 floor 向负无穷取整 才能ac 代码如下 ...
- UVALive 5000 Underwater Snipers --二分
题意:一条河岸线y=k,y>k区域有n个敌人,现在要在y<=k区域布置S个狙击手,狙击手的狙击范围为距离自己半径为D的圆内,问满足能够狙死所有的敌人的情况下,离河岸线最近的那个狙击手的离河 ...
- UVALive 4949 Risk(二分网络流、SAP)
n个区域,每个区域有我方军队a[i],a[i]==0的区域表示敌方区域,输入邻接矩阵.问经过一次调兵,使得我方边界处(与敌军区域邻接的区域)士兵的最小值最大.输出该最大值.调兵从i->j仅当a[ ...
- UVALive 6168 Fat Ninjas --二分小数+搜索
题意:一个NxN的网格地板,有一些激光束从天花板垂直射向地面的某个网格,一个圆要安全地从左走到右,不碰到上边界,下边界以及激光束,问这个圆的直径最大能达到多大. 分析:可以二分直径,关键在check函 ...
- UVALive 6525 Attacking rooks 二分匹配 经典题
题目链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=4536">点击打开链接 题意: ...
- UVALive 4725 Airport(二分)
题目链接 题意 机场有两种飞机,每小时一些飞机到达,每小时安排一架飞机起航.求任意时刻中两种飞机数目的最大值的最小值. 分析 首先肯定是二分来做.这里的难点在于如何判断飞机数目是否合法.一开始忽略了某 ...
随机推荐
- CSS常用样式属性
1.CSS字体和文本相关属性 属性 font-family 规定文本的字体系列,比如:“serif” ''sans-serif" font-size 规定文本的字体尺寸 font-style ...
- Rpgmakermv(32) Yep_mainmenumanager
============================================================================ Introduction ========== ...
- Object-C-Foundation-反射
主要方法和类型 Class 变量名 = [类或者对象 class]; Class 变量名 = [类或者对象 superclass]; Class 变量名 = NSClassFromString(方 ...
- Swift 了解(3)
类(Classes) 假设你是一个建筑师,你刚刚签了一个合同,要在一个新的小区修建20个相似的房子.在你派出建筑工队之前,你必须要画一个房子的设计图.这份设计图将会展现房子的外表和功能.把这份设计图当 ...
- SpringMVC常用注解的规则(用法)
SpringMVC注解 @RequestMapping用法: a. 用在controller方法上: 标记url到请求方法的映射, 其实就是通过一段url地址, 找到对应需要执行的 ...
- mongodb 批量修改
db.getCollection(').find({}).forEach( function(item) { item.date = item.date.replace("2018-11-2 ...
- UART接口与COM口的区别
原文地址:https://blog.csdn.net/wordwarwordwar/article/details/78883732 简单的讲:(UART与COM) 嵌入式里面说的串口,一般是指UAR ...
- 教你如何修改CentOS系统上的时间
直接看命令:
- What Would you Find out about MS908CV ?
The Autel MaxiSYS commercial car diagnostics scan device, No. MS908CV, performs increased technique ...
- mycat水平分表
和垂直分库不同,水平分表,是将那些io频繁,且数据量大的表进行水平切分. 基本的配置和垂直分库一样,我们需要改的就是我们的 schema.xml和rule.xml文件配置(server.xml不用做任 ...