2024.5.17晚训题解

感觉今晚的题目偏思维为主,需要思考

A题题解
因为可以选一个数去赋值,想让数组和变成奇数
那么数组里面必须存在奇数。注意如果是全偶数或者N个数全是奇数但是加来的和是偶数,这都是变不出来的

#include<bits/stdc++.h>
using namespace std;
int A[2005];
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		int s=0;
		int J=0;
		for(int i=1;i<=n;i++){
			scanf("%d",&A[i]);
			s=s+A[i]%2;
			if(A[i]%2)J++;
		}
		s=s%2;
		if(s==0&&J==0||s==0&&J==n)printf("NO\n");//全偶全奇数 
		else printf("YES\n");
	}
	return 0;
}

B题题解
实际上你会发现,如果你每次都全部拿去买东西,一定会把个位上面的亏完,所以我们的策略是每次拿全部大于等于10的整的部分去买东西, 去算返现,把个位留着,加上返现进行下一轮计算

#include<bits/stdc++.h>
using namespace std;
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
	    int s=0;
	    while(n>=10){
	    	s=s+n/10*10;
	    	n=n%10+(n/10);
		}
		printf("%d\n",s+n);
	}
	return 0;
}

C题题解
经典的问题
我们考虑移动的字符串
假如我从起点 S [ 1 ] S[1] S[1]开始走到 S [ k ] S[k] S[k]到达点 ( X , Y ) (X,Y) (X,Y) 接着继续走一段又到达 ( X , Y ) (X,Y) (X,Y),实际上完全可以把 S [ k ] S[k] S[k]后面这一段删了。根据这个思路我们就去记录,到达每个点走了多少步操作数。 这里涉及到坐标的印射,最好使用pair<元素类型,元素类型>+map 去映射 ,pair<>记录的就是二元组,我们可以映射map<pair<元素,元素>,元素> vis ,使用的时候就是vis[make_pari(a,b)]= ?

#include<bits/stdc++.h>
using namespace std;
char s[200005];	
map<pair<int,int>,int>mp;
int main() {
	int p;
	scanf("%d",&p);
	while(p--) {
		int n;
		scanf("%d%s",&n,s+1);
		int d=1e9;
		int x=0,y=0,l=-1,r=-1;
		mp[{0,0}]=0;
		for(int i=1; i<=n; i++) {
			if(s[i]=='L')
				x++;
			if(s[i]=='R')
				x--;
			if(s[i]=='U')
				y++;
			if(s[i]=='D')
				y--;
			if(mp.count({x,y})!=0) {
				//如果当前这个点 在前面已经经过,那么我们尝试删除这段区间
				//取最小删除区间 
				if( (i-mp[{x,y}]) <d){
					d=i-mp[{x,y}];
					l=mp[{x,y}]+1,r=i;
				}
			}
			mp[{x,y}]=i;
		}
		if(l==-1||r==-1) printf("-1\n");
		else printf("%d %d\n",l,r);
		mp.clear();//清空标记 
	}
	return 0;
}


D题 戒网瘾
实际上玩游戏也是需要策略的
具体思路写在代码里面了。能由自己拿分就不用管太多。
不能自己正常拿分那要考虑使用卷轴

#include<bits/stdc++.h>
using namespace std;
int num[200009],e=0,add2=0,y=0;		
int hp[200009],n,a,b,k,add=0,r,change=0;
int main() {
	scanf("%d%d%d%d",&n,&a,&b,&k);
	for(int i=1; i<=n; i++) {
		scanf("%d",&hp[i]);
	}
	for(int i=1; i<=n; i++) {
		int le=hp[i]%(a+b);//前置双人出击很多轮先消掉,再讨论 
		if(le==0){
			//刚好整除说明由对手完成最后一击,是没有分数的
			//倒退回去一轮,依然由自己先手攻击
			//讨论延迟对手几次  能击杀怪物获得分数 
			le=a+b;
		}
		if(le<=a){
			//双人合击后,现在由自己先手,如果怪物的血能被自己一击必杀
			//那么能拿到分数,无需多余讨论 
			add++;
			continue;
		}
		if(le-a>0){
//自己一刀杀不死 
//a砍不死 
//但是对手补一刀怪物必死
//计算要延迟对手多少轮   
			le=le-a;//自己先砍一刀 
			if(le%a==0) {//接下来全由自己攻击,计算次数 
				num[++e]=le/a;
			} else {
				num[++e]=le/a+1;

			}
		}
	}
	sort(num+1,num+e+1);
	//对需要延迟对手攻击,才能取得分数的怪物排序
	//按延迟次数从小到大排序,因为我们的卷轴有限 
	for(int i=1; i<=e; i++) {
		add2=add2+num[i];
		if(add2<=k) {
			y++;
		}else {//卷轴不够了 
			break;
		}
	}
	printf("%d",add+y);
	return 0;
}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值