2024.7.9暑假集训第八场(差HIJK)

23434 Problem  A

危机

题目描述(简述)

请把所有倒计时都转换为以秒作为单位,一天24小时制。

输入

一行6个单词。前4个单词固定为"THE LUNAR CRISIS IN"(不含引号),第5个单词为一个自然数x,第6个单词是一个单位,是以下8个单词之一:DAY,DAYS, HOUR, HOURS, MINUTE, MINUTES,SECOND, SECONDS分别为天、天、时、时、分、分、秒、秒。单词之间以一个空格隔开。

输出

一行6个单词。前4个单词固定为"THE LUNAR CRISIS IN"(不含引号),第5个单词为一个自然数,第6个单词固定为秒,是SECOND或SECONDS之间的一个。要求输入输出的时间长度相等。单词之间以一个空格隔开。

思路:大海呀,全是水(难得一见的水题)

代码:

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
using namespace std;
int main()
{
	string s;
	for(int i=1;i<=4;i++)
		cin>>s;
	long long n;
	cin>>n;
	cin>>s;
	cout<<"THE LUNAR CRISIS IN ";
	if(s=="DAY")
	{
		cout<<"86400 SECONDS";
	}
	else if(s=="DAYS")
	{
		cout<<n*86400<<" SECONDS";
	}
	else if(s=="HOUR")
	{
		cout<<3600<<" SECONDS";
	}else if(s=="HOURS")
	{
		n=n*60*60;
		cout<<n<<" SECONDS";
	}else if(s=="MINUTE")
	{
		cout<<60<<" SECONDS";
	}else if(s=="MINUTES")
	{
		n=n*60;
		cout<<n<<" SECONDS";
	}else if(s=="SECOND")
	{
		cout<<"1 SECOND";
	}
	else if(s=="SECONDS")
	{
		cout<<n<<" SECONDS";
	}
	return 0;
}

23435 Problem  B

密钥

题目描述(简述)

给出一个密钥在两种不同进制下表示的字符串,你能否破译出它们分别是什么进制呢?
注意:我们只考虑2 − 36进制。

输入

两个由数字、大写字母构成的字符串s,t,以空格隔开。

输出

两个整数a, b,中间以空格隔开。表示a进制下的s与b进制下的t相等(且要求2 ≤ a, b ≤ 36)。
若有多对a, b满足条件,输出a最小的那一对;若仍有多对,则输出b最小的那一对;若不存在a, b满足条件,则认为a = b = 0。

提示


对于100%的数据,1 ≤ |s|, |t| ≤ 12, s ≠ 0,t ≠ 0。其中|s|, |t|分别表示字符串的长度

思路:s或t中如果出现k,那它至少k+1进制,算出每种可能的进制以后对比就好

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
char aa[20],ba[20];
int a[20],b[20];
struct node{
	int jz;
	long long v;
}ans[3][40];
int la,lb,h[3]={};
void sol(int x,int id)
{
	long long anss=0;
	if(id==1) 
		for(int i=1;i<=la;i++)
			anss=anss*x+a[i];
	else
		for(int i=1;i<=lb;i++)
			anss=anss*x+b[i];
	ans[id][++h[id]].jz=x;
	ans[id][h[id]].v=anss;
}
bool cmpn(node a,node b)
{
	if(a.v==b.v)
		return a.jz<b.jz;
	return a.v<b.v;
}
int main()
{
	cin>>aa+1>>ba+1;
	int maxa=0,maxb=0;
	lb=strlen(ba+1);
	la=strlen(aa+1);
	for(int i=1;i<=la;i++)
	{
		if(aa[i]<='9'&&aa[i]>='0')
			a[i]=aa[i]-'0';
		else
			a[i]=aa[i]-'A'+10;
		maxa=max(maxa,a[i]);
	}
	for(int i=maxa+1;i<=36;i++)
		sol(i,1);
	for(int i=1;i<=lb;i++)
	{
		if(ba[i]<='9'&&ba[i]>='0')
			b[i]=ba[i]-'0';
		else
			b[i]=ba[i]-'A'+10;
		maxb=max(maxb,b[i]);		
	}
	for(int i=maxb+1;i<=36;i++)
		sol(i,2);
	sort(ans[1]+1,ans[1]+h[1]+1,cmpn);
	sort(ans[2]+1,ans[2]+h[2]+1,cmpn);
	for(int i=1,j=1;i<=h[1]&&j<=h[2];)
	{
		if(ans[1][i].v>ans[2][j].v)
			j++;
		else if(ans[1][i].v<ans[2][j].v)
			i++;
		else
		{
			cout<<ans[1][i].jz<<' '<<ans[2][j].jz;
			return 0;
		}
	}
	printf("0 0");
	return 0;
}

23436 Problem  C

防空

题目描述(简述)

时间单位采用微秒,角度单位采用秒。每一颗陨石都有一个位置方向(方位角),用0 − 1295999之间的整数表示。每个陨石还有一个正整数的稳定度,当稳定度下降为0或更低后,其结构瓦解。
每台防空机枪最开始都有一个朝向角度。检测到陨石的方向后,在每1微秒时间中,每一台防空机枪可以执行下列三项指令之一:顺时针旋转1秒;逆时针旋转1秒;发射1枚子弹。其影响分别为:
朝向角度+1(若达到1296000则变为0);朝向角度−1(若达到−1则变为1295999);使陨石的稳定度−1(前提是这台防空机枪的朝向角度等于陨石的位置方向)。
对于每一颗陨石,请尽快计算出确定其方向后瓦解它所需要的最短时间以便后续决策。特别的,每当一颗陨石被瓦解后,所有防空机枪的朝向会自动恢复到其初始值,因而不同陨石之间互不影响。
同时,数十年后的子弹科技水平超出通常理解范围,其发射后的飞行时间可以忽略不计。

输入

第一行两个正整数n, m,分别表示防空炮、陨石的数量。
第二行n个整数ai,以空格隔开,表示第i台防空机枪的初始朝向角度值(单位为秒)。
接下来m行每行两个整数A,H分别表示每颗陨石的位置角度(单位为秒)和稳定度。

输出

m行每行一个整数,表示瓦解这颗陨石所需要的最短时间(单位为微秒)。

样例输入 Copy
3 2
1295998 1 1
1 3
1295999 10
样例输出 Copy
2
5
提示

样例解释:
对第一颗陨石:后两台机枪持续射击,而第一台机枪由于角度不对无法射击;在1微秒后,陨石的稳定度下降至1;第2微秒后,下降为−1,瓦解。共需2微秒。
对第二颗陨石:所有机枪都需要先旋转后射击,第一台顺时针,后两台逆时针。1微秒后第一台达到预期角度,后两台达到0秒角度。第2微秒中,第一台机枪进行射击,而后两台机枪逆时针旋转到1295999秒的角度,稳定度下降为9。此后每1微秒中三台机枪均进行射击,第3、4、5微秒后的稳定度分别下降为6、3、0。陨石于共5微秒后瓦解。
对于100%的数据, 1 ≤ n, m ≤ 1000, 0 ≤ ai, A ≤ 1295999, 1 ≤ H ≤ 109

思路:我服了为什么题目要这么冗长...第一遍读完以后没敢写,感觉很容易超时,做了几道以后发现剩下的只有这道能切一下所以回来了...最开始的想法是依照方向角遍历,复杂度n*648000,结果超时了omg。于是切换角度依照n遍历,omg,居然过了,所以就是说em费劲想了半天结果复杂度还不如直接做(sad)。做题时遇到的问题是就是说机枪距离陨石的距离的计算,后来调出来了,下次注意(注释掉的代码是第一遍的错误思路)

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int a[3000010]={},b[1010],aa[1010];
int n,m,x;
bool cmpn(int a,int b)
{
	return min((a+1296000-x)%1296000,(x-a+1296000)%1296000)<min((b+1296000-x)%1296000,(x-b+1296000)%1296000);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&aa[i]);
	//	a[aa[i]]++;
	//	a[aa[i]+1296000]++;
	}
	int h,sumn;
	for(int i=1;i<=m;i++)
	{
		sumn=0;
		scanf("%d%d",&x,&h);
		long long j=0;
		/*if(a[x]!=0)
			sumn=a[x];
		for(;j<=648000;j++)
		{
			h=h-sumn;
			if(h<=0)
				break;
			if(a[x+j]!=0)
				sumn+=a[x+j];
			if(a[x-j]!=0)
				sumn+=a[x-j];
		}*/
		sort(aa+1,aa+1+n,cmpn);
		for(int i=1;i<=n;i++)
			b[i]=min((aa[i]+1296000-x)%1296000,(x-aa[i]+1296000)%1296000);
		/*for(int i=1;i<=n;i++)
			cout<<b[i]<<' ';
			cout<<endl;*/
		for(int i=1;i<=n;i++)
		{
			if(h<=sumn*(b[i]-b[i-1]))
			{
				if(h%sumn==0)
					j=j+h/sumn;
				else
					j=j+h/sumn+1;
				h=0;
				break;
			}
			h-=sumn*(b[i]-b[i-1]);
			j=j+b[i]-b[i-1];
			sumn+=1;
		}
		if(h==0)
			printf("%lld\n",j);
		else
		{
			if(h%sumn==0)
			printf("%lld\n",j+h/sumn);
			else
			printf("%lld\n",j+h/sumn+1);
		}
	
	}
	return 0;
}

23437 Problem  D

生命

题目描述(简述)

系统不定期会收到以下形式的消息:“name x”,其中name是长度不超过20的英文字母构成的非空字符串,表示一个队员的名字;x则表示有事件发生或结束了。若x ≠ 0,则说明队员遭遇了一个影响为x的事件;若x = 0,则说明发生在这名队员身上的尚未结束的事件中,最早发生的一个结束了(特别的,如果这个队员没有任何尚未结束的事件,则这条消息不结束任何事件)。
系统需要时刻关注每个队员受到的总影响。具体而言,每当接收到一条消息后,系统需要输出这条消息涉及的队员,发生在他身上的所有尚未结束的事件的影响值的加法总和。

输入

第一行一个整数n,表示消息的数量。
接下来n行每行一个非空字符串name和一个整数x,以空格隔开,含义如上所述。

输出

n行每行一个整数,发生在对应队员身上所有尚未结束的事件的影响之和。

样例输入 Copy
8
DeepinC 3
DeepinC 2
Somebody 1
DeepinC 0
DeepinC 4
DeepinC 0
DeepinC 0
DeepinC 0
样例输出 Copy
3
5
1
2
6
4
0
0
提示

对于100%的数据,n ≤ 105, |x| < 109, name为长度介于1与20之间的英文字母字符串

思路:一眼stl,但是,嘻嘻,忘了是该用哪个了,嘻嘻(被打),于是查了一圈map,queue,vector,stack。然后做的。(其实没什么含金量的题目,但是就是说我也没什么含金量

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
map<string,queue<int>>a;
map<string,long long>ansa;
int n;
int main()
{
	string s;
	int x;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		cin>>s>>x;
		if(x==0&&a[s].empty()==false)
		{
			ansa[s]-=a[s].front();
			cout<<ansa[s]<<endl;
			a[s].pop();
		}
		else if(x==0)
		{
			cout<<ansa[s]<<endl;
		}
		else if(x!=0)
		{
			a[s].push(x);
			ansa[s]+=a[s].back();
			cout<<ansa[s]<<endl;
		}
	} 
	return 0;
}

map:C++ map的常用用法(超详细)(*^ー^)人(^ー^*)_c++ map用法-CSDN博客

queue:

23438 Problem  E

仓鼠小队

题目描述(简述)


唐克老师打算把自己养的 n 只仓鼠三只一组放在一个笼子里养
而每只仓鼠有一个战斗力 ai 来表示第 i 只仓鼠的战斗力
而一只笼子里的三只仓鼠战斗力分别为 [x1,x2,x3] 的话
这只笼子的安全程度即为 max(x1,x2,x3) - min(x1,x2,x3)
现在唐克老师想知道,怎么分配仓鼠可以使得每只笼子的安全程度之和最小?

输入

第一行输入一个正整数 n,保证 n 是 3 的倍数。
接下来一行输入 n 个正整数 ai

输出

输出一行一个整数表示答案。

提示

n<=10^5,ai<=10^9

思路:没什么好说的,做之前看到没人对还以为有坑,结果没有,于是抢先一步a了嘻嘻

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,a[100010];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	sort(a+1,a+1+n);
	long long ans=0;
	for(int i=1;i<=n;i=i+3)
	{
		ans=ans+a[i+2]-a[i];
	}
	printf("%lld",ans);
	return 0;
}

23439 Problem  F

羊腿出售

题目描述(简述)

现在唐克老师一共拿出了 n 只羊腿,编号分别为 1 ~ n,并且每只羊腿的品质等级为 ai
张老师将会提出 m 次问题,每次询问会指向一段连续编号的羊腿,要求唐克老师从中选出两只对应品质的羊腿
现在唐克老师告诉张老师他有多少种不同的选法能满足这两只羊腿,选出的两只羊腿的相对顺序按照张老师的要求!
也就是说如果有这样的 9 只羊腿,品质分别为 aaabbbccc
现在张老师给出的问题是在 [2,5],即 aabb 中选出 ab 两只羊腿
则唐克老师会给出 4 种不同的方案:(2,4),(2,5),(3,4),(3,5)
如果张老师给出的询问是在 [1,3],即 aaa 中选出 aa 两只羊腿
则唐克老师会给出 3 种不同的方案:(1,2),(1,3),(2,3)
现在张老师想知道,对于他提出的每一个询问正确答案应该是多少,以此来验证唐克老师的答案是否正确

输入

输入第一行包含两个整数 n,m 表示有 n 只羊腿和张老师会提出 m 次问题
第二行包含一个长度为 n 的字符串 a,分别表示 n 只羊腿的品质
接下来 m 行,每行包含两个整数 l,r 和一个长度为 2 的字符串,表示张老师的一次提问

输出

对于每一次提问输出一个正整数表示答案

提示

思路:不难,对每个字母存羊腿序号,然后正常搜

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int a[30][200010],h[30]={};
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	char c;
	for(int i=1;i<=n;i++)
	{
		cin>>c;
		a[c-'a'][++h[c-'a']]=i;
	}
	int x,y;
	int sum[5];
	char s[5];
	while(m--)
	{
		cin>>x>>y>>s;
		sum[1]=0,sum[0]=0;
		for(int i=0;i<=1;i++)
		{
			for(int j=1;j<=h[s[i]-'a'];j++)
			{
				if(a[s[i]-'a'][j]>y)
					break;
				if(a[s[i]-'a'][j]>=x)
					sum[i]++;
			}
		}
		if(s[0]==s[1])
			cout<<sum[0]*(sum[0]-1)/2<<endl;
		else
			cout<<sum[0]*sum[1]<<endl;
	}
	return 0;
} 

23440 Problem  G

数字拼接

题目描述

众所周知,唐克老师在暑假期间切割了很多的数字,把手里的数字切割成了更小的数字
现在他发现手里一共留下了 n 个数字,分别为 a1,a2 ... an
他现在希望从中选出 m 个数字拼成一个数字
例如他有 3 个数字 1,23,4,选两个数字拼成一个数字的方案有 123,231,14,41,234,423 这六种方案
现在唐克老师想知道,他手里的数字一共能组成多少种不同的数字?

输入

输入第一行包含两个整数 n,m,分别表示数字的个数和需要选的数字个数
第二行包含 n 个整数 ai,表示数字

输出

输出唐克老师一共能拼出多少种不同的数字

样例输入 Copy
3 2
1 23 4
样例输出 Copy
6
提示

思路:首a?偷了耶,偷水题专家(并不是),dfs

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;
string a[10010],s[15];
int vis[15]={};
int n,m,h=0;
void sol(int x,string now)
{
	if(x==m)
	{
		a[++h]=now;
		return;
	}
	for(int i=1;i<=n;i++)
	{
		if(vis[i]!=0)
			continue;
		string ls=now;
		now=now+s[i];
		vis[i]=1;
		sol(x+1,now);
		now=ls;
		vis[i]=0;
	}
	return;
}
bool cmpn(string a,string b)
{
	return a<b;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		cin>>s[i];
	sol(0,"");
	sort(a+1,a+1+h,cmpn);
	int sumn=0;
	for(int i=1;i<=h;i++)
	{
		if(a[i+1]==a[i])
			continue;
		sumn++;
	}
	printf("%d",sumn);
	return 0;
}

23441 Problem  H

倒水计划plus

15492 Problem  I

壕游戏

15493 Problem  J

密码

15494 Problem  K

大新闻

  • 30
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是使用 C++ 编写的求字符串中最长的字母子串的代码实现: ```cpp #include <iostream> #include <cstring> using namespace std; int main() { string s = "abc123defg456hijk"; int n = s.size(); int start = 0, len = 0; // 记录最长子串的起始位置和长度 for (int i = 0; i < n; i++) { // 遍历字符串 if (!isalpha(s[i])) { // 如果当前字符不是字母,更新起始位置 start = i + 1; continue; } int j = i + 1; while (j < n && isalpha(s[j])) { // 找到当前字母子串的结束位置 j++; } int cur_len = j - i; // 当前字母子串的长度 if (cur_len > len) { // 如果当前字母子串更长,更新最长子串的起始位置和长度 start = i; len = cur_len; } } string longest_substring = s.substr(start, len); // 提取最长子串 cout << "最长的字母子串是:" << longest_substring << endl; return 0; } ``` 在这个程序中,我们首先定义了一个字符串 `s`,表示所给出的字符串。然后,我们使用一个变量 `start` 记录当前字母子串的起始位置,使用一个变量 `len` 记录最长子串的长度,初始值都为0。 接下来,我们使用一个循环遍历字符串中的每一个字符。如果当前字符不是字母,说明前面的字母子串已经结束,我们需要更新 `start` 的值,使其指向下一个字母子串的起始位置。如果当前字符是字母,我们需要找到当前字母子串的结束位置 `j`,具体方法是从当前位置开始向后遍历,直到遇到第一个非字母字符或字符串结束。然后,我们计算当前字母子串的长度 `cur_len`,如果它大于 `len`,说明当前字母子串更长,我们需要更新最长子串的起始位置和长度。 最后,我们使用 `substr()` 函数提取最长子串,并输出结果。 需要注意的是,我们使用了 C++ 中的 `isalpha()` 函数来判断一个字符是否是字母。另外,由于本题中只考虑英文字母,因此代码中没有考虑其他字符,如数字、标点符号等。在实际使用中,需要根据实际情况进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值