E. Superhero Battle
题意
有一个怪兽,初始血量为HHH,他的血量变化情况是一个长度为nnn轮的周期。问怪兽会在第几轮死去。
1≤H≤10121 \leq H \leq 10^{12}1≤H≤1012
1≤n≤2×1051 \leq n \leq 2 \times 10^51≤n≤2×105
做法
首先如果怪兽血量在一个周期内不曾小于等于000而且每个周期之后怪兽血量增加,直接输出?1-1?1。
之后要知道,怪兽在某个完整的周期之前到达x血量,怪兽就撑不过这轮。
这个xxx的求法就是遍历一遍周期,找到某个时刻怪兽血量消耗最多。
之后就假设怪兽初始血量为H?xH-xH?x。看怪兽能撑过几个完整的轮,设这里轮数为kkk,每轮怪兽血量减少sumsumsum,则要满足
sum×k+x≥Hsum\times k+x\ge H sum×k+x≥H
k≥H?xsumk\ge \frac{H-x}{sum} k≥sumH?x?
所以不等式右面要上取整得到kkk,之后再O(n)O(n)O(n)的进行一个周期看怪兽在第几轮死即可。
代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 2e5+5;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
int a[maxn];
int n;
ll H;
ll sum;
int check(ll mid)
{
ll tt=H;tt+=(mid-1)*sum;if(tt<=0) return 0;for(int i=1;i<=n;i++){
tt+=a[i];if(tt<=0) return i;}return -1;
}
int main()
{
scanf("%lld%d",&H,&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);sum=0;int flag=0;ll tmp=H;ll minn=LL_INF;int pos;for(int i=1;i<=n;i++){
sum+=a[i];tmp+=a[i];if(sum<minn){
minn=sum;pos=i;}if(tmp<=0){
flag=i;break;}}if(flag!=0){
printf("%d\n",flag);return 0;}if(sum>=0){
printf("-1");return 0;}minn=-minn;sum=-sum;ll ans=(H-minn)/sum+((H-minn)%sum!=0);H=H-ans*sum;if(H==0){
printf("%lld\n",ans*n);return 0;}for(int i=1;i<=n;i++){
H+=a[i];if(H<=0){
printf("%lld\n",ans*n+i);return 0;}}return 0;
}