C. Monsters And Spells

目录

C. Monsters And Spells 

题意理解

题解        

AC代码

B. Minor Reduction

 原题描述

题解 

AC代码

A. Equidistant Letters

题解

AC代码

D. Martial Arts Tournament

题解

AC代码


C. Monsters And Spells 

原题描述

题意理解

        这是一个游戏。在第i秒时,可能会出现血量为hi的怪兽。所幸你会魔法,你释放法术造成的伤害和你已经连续释放次数是相同的,比如你连续释放3次法术,这三次依次能造成的伤害为1,2,3,你随时可以重置连续释放次数,如比可以造成如下伤害1,2,3,1,2。你要在每一只怪物出现那一刻用法术把他消灭掉。在没有怪物时也能释放法术。释放法术是需要魔力值的,释放一个法术所花费的魔力值与该法术可能造成的伤害相同。

        输入怪物的数量,然后是出现怪物的时刻和该怪物的血量。输出最小的法力值花费。

举例

        有3只怪兽出现在第5,7,9秒,血量依次为2,1,2。

        我们在第4秒时开始释放法术,当前伤害为1,花费1点法力。第五秒伤害为2,花费2点法力,正好与第五秒出现怪兽的血量相同。第六秒不释放,第七秒释放一次,伤害与血量相同,花费1点法力。第8秒重置连续释放次数,造成伤害为1,花费1点法力。第9秒,连续释放,造成伤害为2,与怪物血量对应,花费2点法力。

        总的法力花费为1+2+1+1+2=7。

        输出7即可。

题解        

        我们关注怪物出现的时刻法术的伤害。

        因为我们要追求最小的法术消耗,所以我们假定在第i只怪兽时,我们法术的伤害等于该怪兽的血量。

        什么情况下该假设不能成立呢?

        1.第i时刻与i-1时刻的间隔小于怪兽的血量时。

        2.值得注意的是,必须满足所有的怪兽都能受到大于他们血量的攻击。假设我们当前的法术伤害一直叠加,但是到了某一只怪兽出现时无法大于他的血量,代表着我们当前的法术伤害低了。

        以上两种情况下我们的假设都不成立。

        对于第一种,我们当前释放的法术伤害等于对前一只怪兽释放的法术加上两个时刻的间隔。

        对于第二种,我们直接将可以满足该条件的最小值当作假设值,再带到第一个条件里面判断,如果大于i与i-1的时间间隔,改假设值成立,否则当前释放的法术伤害等于对前一只怪兽释放的法术加上两个时刻的间隔。

AC代码

/*@_krito*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define LM LLONG_MAX
#define IM INT_MAX
#define _for(i,a,b) for(int i=a;i<=b;i++)
#define N 101
struct monster{
	ll s;
	ll h;
};
ll sum1(ll x){
	return (1+x)*x/2;
}
int main(){
	int t;
	cin>>t;
	while(t--){
		ll n,ans=0,temp=0;
		monster a[N];
		cin>>n;
		_for(i,1,n) cin>>a[i].s;
		_for(i,1,n) cin>>a[i].h;
		a[0].s=0;
		a[0].h=0;
		int temp1=0;
		_for(i,1,n){
			ll temp=a[i].h;
			_for(j,i+1,n) if(a[j].h-temp>a[j].s-a[i].s) temp=a[j].h-(a[j].s-a[i].s);
			if(a[i].s-a[i-1].s>=temp){
			    ans+=sum1(temp);
				temp1=temp;
//				cout<<ans<<endl;
		}
		else{
			ans+=sum1(temp1+a[i].s-a[i-1].s)-sum1(temp1);
//			cout<<ans<<endl;
			temp1=temp1+a[i].s-a[i-1].s;
		}
	}
	cout<<ans<<endl;
	
}
}

B. Minor Reduction

 原题描述

 

题解 

        第一次从后往前遍历字符串,如果两相邻数字相加大于10,进行操作,然后退出,输出即可。

        如果没有一对数字相加大于10,直接对第一个数和第二个数操作放到字符串里面输出即可。

AC代码

/*@_krito*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define LM LLONG_MAX
#define IM INT_MAX
#define _for(i,a,b) for(int i=a;i<=b;i++)
#define N 200002
int main(){
	int t;
	cin>>t;
	while(t--){
		char s[N];
		bool flag=true;
		cin>>s;
		int len=strlen(s);
		for(int i=len-1;i>=1;i--){
			int temp=s[i]+s[i-1]-'0'-'0';
			if(temp>=10){
				s[i]=temp%10+'0';
				s[i-1]=temp/10+'0';
				flag=false;
				break;
			}
		}
		if(flag){
		s[1]=s[0]+s[1]-'0';
		_for(i,1,len-1){
			cout<<s[i];
		}
	}
	 else 	_for(i,0,len-1)
	 	cout<<s[i];
		cout<<endl;
	}
}

A. Equidistant Letters

题解

        拿一个数组当桶,记录字母出现个数,然后输出即可。

AC代码

/*@_krito*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define LM LLONG_MAX
#define IM INT_MAX
#define _for(i,a,b) for(int i=a;i<=b;i++)

int main(){
	int t;
	cin>>t;
	while(t--){
		string s;
		int a[30]={0};
		cin>>s;
		int len=s.length();
		_for(i,0,len-1){
			a[s[i]-'a']++;
		}
		_for(i,0,25){
			if(a[i]==0) continue;
			if(a[i]==1){
				char temp=i+'a';
				cout<<temp;
			}
			if(a[i]==2){
				char temp=i+'a';
				cout<<temp<<temp; 
			}
		}
		cout<<endl;
	}
}

D. Martial Arts Tournament

题解

        暴力求解,直接模拟出所有x,y可能的取值即可。

AC代码

/*@_krito*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define LM LLONG_MAX
#define IM INT_MAX
#define _for(i,a,b) for(int i=a;i<=b;i++)
#define N 200010
int n;
int s[N];
int cmp(int x,int y){
//	cout<<x<<y<<endl;
	int temp1=1,temp2=1,temp3=1;
	while(temp1<x) temp1*=2;
	while(temp2<y-x) temp2*=2;
	while(temp3<n-y) temp3*=2;
	return temp1-x+temp2-y+x+temp3-n+y;
}
int main(){
	int t;
	cin>>t;
	while(t--){
		int a[N]={0},ans=IM;
		scanf("%d",&n);
		_for(i,1,n){
			int x;
			scanf("%d",&x);
			a[x]++;
	}
	    _for(i,1,n){
	    	s[i]=s[i-1]+a[i];
		}
		_for(i,1,n+1){
			int tempx=s[i-1];
			for(int j=0;(1<<j)<=n-tempx;j++){
				if(j==1){
					int tempy= upper_bound(s+1,s+1+n,tempx+j)-s;
				tempy=s[tempy-1];
				ans=min(ans,cmp(tempx,tempy));
				tempy=lower_bound(s+1,s+1+n,n-j)-s+1;
				tempy=s[tempy-1];
				ans=min(ans,cmp(tempx,tempy));
				}
				int tempy= upper_bound(s+1,s+1+n,tempx+(1<<j))-s;
				tempy=s[tempy-1];
				ans=min(ans,cmp(tempx,tempy));
				tempy=lower_bound(s+1,s+1+n,n-(1<<j))-s+1;
				tempy=s[tempy-1];
				ans=min(ans,cmp(tempx,tempy));
			}
		}
		printf("%d\n",ans);
	}
} 
 

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Krito.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值