当前位置: 代码迷 >> 综合 >> 【Codeforces Round #547 (Div. 3) E. Superhero Battle】思维题
  详细解决方案

【Codeforces Round #547 (Div. 3) E. Superhero Battle】思维题

热度:25   发布时间:2023-12-29 02:04:03.0

E. Superhero Battle

题意

有一个怪兽,初始血量为HHH,他的血量变化情况是一个长度为nnn轮的周期。问怪兽会在第几轮死去。

1≤H≤10121 \leq H \leq 10^{12}1H1012
1≤n≤2×1051 \leq n \leq 2 \times 10^51n2×105
做法

首先如果怪兽血量在一个周期内不曾小于等于000而且每个周期之后怪兽血量增加,直接输出?1-1?1
之后要知道,怪兽在某个完整的周期之前到达x血量,怪兽就撑不过这轮。
这个xxx的求法就是遍历一遍周期,找到某个时刻怪兽血量消耗最多。
之后就假设怪兽初始血量为H?xH-xH?x。看怪兽能撑过几个完整的轮,设这里轮数为kkk,每轮怪兽血量减少sumsumsum,则要满足
sum×k+x≥Hsum\times k+x\ge H sum×k+xH
k≥H?xsumk\ge \frac{H-x}{sum} ksumH?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;
}
  相关解决方案