NEUQ-ACM预备队第三次双周赛题解

T1. 打字

如果你仍然再用二指禅打字,那我建议你重新学习打字,这样你打字会更快,感觉更舒适和愉快。

有很多网站教授正确的打字。下图描述了基本原理: 用同一手指按压颜色相同的键。黄色键需要用小指按压,蓝色的用无名指,绿色的用中指,红色的用食指。

另外,左手按键盘的左侧(从左侧的5、T、G、B键开始)右手按压右侧(从右侧的键6、Y、H、N开始)。拇指负责空格键。

图片描述的键盘是美式键盘。

现在,给出一段长度为 len(1≤len≤50) 的字符串,请你计算如果正确打出这个字符串,每个手指敲击键盘的次数。

输入格式:

输入为一行,一个由大写字母、数字和特殊符号组成的字符串(不包括空格,不需要管图片中未显示的按键)。

输出格式:

输出8行,表示左手小指、无名指、中指、食指以及右手食指、中指、无名指、小指敲击键盘的次数。

输入样例1:

AON=BOO; 

输出样例1:

1
0
0
1
1
0
3
2

输入样例2:

PRINT'NY'[NASLA] 

输出样例2:

2
1
0
2
4
1
1
5

 这道题用一堆if else把所有情况全列出来然后用变量存一下,后面直接输出就可以

#include<iostream>
using namespace std;

int main(){
    int click[8]={0};
    char ch;
    while((ch=getchar())!=EOF){
        if(ch=='Z'||ch=='A'||ch=='Q'||ch=='1')click[0]++;
        else if(ch=='X'||ch=='S'||ch=='W'||ch=='2')click[1]++;
        else if(ch=='E'||ch=='D'||ch=='C'||ch=='3')click[2]++;
        else if(ch=='V'||ch=='F'||ch=='R'||ch=='4')click[3]++;
        else if(ch=='B'||ch=='G'||ch=='T'||ch=='5')click[3]++;
        else if(ch=='N'||ch=='H'||ch=='Y'||ch=='6')click[4]++;
        else if(ch=='M'||ch=='J'||ch=='U'||ch=='7')click[4]++;
        else if(ch==','||ch=='K'||ch=='I'||ch=='8')click[5]++;
        else if(ch=='.'||ch=='L'||ch=='O'||ch=='9')click[6]++;
        else if(ch=='/'||ch==';'||ch=='P'||ch=='0')click[7]++;
        else if(ch=='['||ch==']'||ch=='\''||ch=='-'||ch=='=')click[7]++;
    }
    for(int i = 0;i < 8;i++){
        cout << click[i] << endl;
    }
    return 0;
}

T2.分香肠

有 N 根完全相同的香肠, 现在要平均分给 M 个客人。 问最少需要切几刀才能将其平均分给客人(不能多个香肠一起切)。

输入格式:

两个整数 N(1≤N≤105) 和 M(1≤M≤105)

输出格式:

一个整数,表示要切的刀数

输入样例:

在这里给出一组输入。例如:

2 6

输出样例:

在这里给出相应的输出。例如:

4

n个香肠给m个客人吃,我们先让n取模于m,多出来的那些我们可以不切割直接平分,只考虑多出来的那一部分,然后n和m求一个最大公因数,接着让他们都除以最大公因数,易得m-1就是这n个香肠给m个客人吃的最小切割数,然后让这个数乘以最大公因数就得到答案了,不过注意m正好是n的因数的情况,以防出现除数为零的情况,加个特判就可以,AC代码附上

#include <iostream>
#include <cmath>
using namespace std;

int gcd(int n,int m){
    while(m%n){
        int temp = n;
        n = m%n;
        m = temp;
    }
    return n;
}

int main() {
	int N, M;
	cin >> N >> M;
	N = N % M;
    if(N==0)cout << 0 << endl;
    else {
        int temp = gcd(N,M);
      cout << M-temp << endl;
    }
	return 0;
}

T3.会议安排

学校的礼堂每天都会有许多活动,有时间这些活动的计划时间会发生冲突,需要选择出一些活动进行举办。小刘的工作就是安排学校礼堂的活动,每个时间最多安排一个活动。现在小刘有一些活动计划的时间表,他想尽可能的安排更多的活动,请问他该如何安排。

输入格式:

第一行是一个整型数m(m<100)表示共有m组测试数据。
每组测试数据的第一行是一个整数n(1<n<10000)表示该测试数据共有n个活动。
随后的n行,每行有两个正整数Bi,Ei(0<=Bi,Ei<10000),分别表示第i个活动的起始与结束时间(Bi<=Ei)

输出格式:

对于每一组输入,输出最多能够安排的活动数量。
每组的输出占一行

输入样例:

在这里给出一组输入。例如:

2
2
1 10
10 11
3
1 10
9 11
11 20

输出样例:

在这里给出相应的输出。例如:

2
2

 会议安排的话直接用贪心,先把这些会议以结束时间排好,然后一个一个遍历过去,只要能安排就安排,用一个变量来存一下结束时间,只要下一个会议的开始时间晚于这个结束时间就可以安排上,然后更新一下这个结束时间,顺便cnt++,遍历完之后输出答案即可

#include<iostream>
#include<algorithm>
using namespace std;

struct huiyi{
    int kaishi;
    int jieshu;
};

bool cmp(huiyi &a,huiyi &b){
    return a.jieshu<b.jieshu;
}

int main(){
    int n;
    huiyi hy[10005];
    cin >> n;
    for(int i = 0;i < n;i++){
        int m;
        cin >> m;
        for(int j = 0;j < m;j++){
            cin >> hy[j].kaishi >> hy[j].jieshu;
        }
        sort(hy,hy+m,cmp);
        int tim = 0;
        int cnt = 0;
        for(int j = 0;j < m;j++){
            if(hy[j].kaishi>=tim)tim = hy[j].jieshu,cnt++;
        }
        cout << cnt << endl;
    }
}

T4.神秘密码

传说二战时X国收到了上帝的一串密码,只有解开密码,才能阻止战争的继续进行,世界才会恢复和平。解开密码的第一道工序就是解压缩密码,上帝对于连续的若干个相同的子串"X"会压缩为"[DX]"的形式(D是一个整数且1<=D<=99),比如说字符串"CBCBCBCB"就压缩为"[4CB]"或者"[2[2CB]]",类似于后面这种压缩之后再压缩的称为二重压缩。如果是"[2[2[2CB]]]"则是三重的。现在我们给你上帝发送的密码,请你对其进行解压缩。

输入格式:

一个字符串。

输出格式:

一个字符串。

输入样例:

在这里给出一组输入。例如:

AC[3FUN]

输出样例:

在这里给出相应的输出。例如:

ACFUNFUNFUN

【数据范围】

解压后的字符串长度在 20000 以内,最多只有十重压缩。保证只包含数字、大写字母、[ 和 ]

这个密码的结构看起来就很递归,我们用一个递归函数来解这个字符串,如果读到的是大写字母就直接加在答案后面,如果是 [ 就说明有压缩的部分了,接着调用这个函数继续解压后续的内容,读到 ] 就代表压缩结束,返回这个字符串给上一级递归,然后把这个字符串复制n次加在答案后面,最后返回整个字符串输出即可,编写时注意压缩的次数在上一级递归中输入并存储,让下一级递归直接从字母或者 [ 开始,否则很难写

#include<iostream>
#include<cstring>
using namespace std;

string jieya(){
    string a,b;
    int n;
    char c;
    while(cin >> c){
        if(c == '['){
            cin >> n;
            b = jieya();
            while(n--)a+=b;
        }
        else if(c==']')return a;
        else a+=c;
    }
    return a;
}

int main(){
    string ans = jieya();
    cout << ans <<endl;
    return 0;
}

T5.国王游戏

恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。
首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。
然后,让这 n 位大臣排成一排,国王站在队伍的最前面。
排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:
排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。
注意,国王的位置始终在队伍的最前面。

输入格式:

第一行包含一个整数 n(1≤n≤1000),表示大臣的人数。
第二行包含两个整数 a (0<a)和 b(b<10000),之间用一个空格隔开,分别表示国王左手和右手上的整数。
接下来 n 行,每行包含两个整数 a 和 b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。

输出格式:

输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。

输入样例:

在这里给出一组输入。例如:

3
1 1
2 3
7 4
4 6

输出样例:

在这里给出相应的输出。例如:

2

 首先注意一点计算金币的时候是这位大臣前面所有人左手的乘积除以自己右手的数得到的,乘积不包括自己的左手,然后就是解题的关键了,对于其中相邻两个人,易得交换他们两个的位置对其他人的金币不造成影响,仅考虑他们两个人,设他们左右手的数字分别为l1,r1,l2,r2;易得交换前这两个人的金币为(设前面所有人的左手乘积为n)

                第一个人        第二个人

交换前        n/r1                n*l1/r2

交换后        n/r2                n*l2/r1

                第一个人        第二个人

交换前        r2                    l1*r1

交换后        r1                    l2*r2

若前一个人的左右手乘积大于后一个人 即l1*r1大于l2*r2,易得

max(r1,l2*r2) <= l1*r1 <=max(r2,l1*r1)

所以我们根据左右手的乘积来给大臣排序,得到的最大金币只会小于等于原来的最大金币,还有一点是这道题的数据会比较大,所以我们需要写高精度来计算,AC代码附上

#include <iostream>
#include <algorithm>
#define MAXLEN 10000
using namespace std;

int temp[MAXLEN] = {0};

struct p {
	int zuoshou;
	int youshou;
};

bool bijiao(int m[], int n[]) {
	for (int i = MAXLEN - 1; i >= 0; i--) {
		if (m[i] > n[i])
			return 1;
	}
	return 0;
}

void cheng(int m[], int n) {
	for (int i = 0; i < MAXLEN; i++) {
		m[i] *= n;
	}
	for (int i = 0; i < MAXLEN; i++) {
		m[i + 1] += m[i] / 10;
		m[i] %= 10;
	}
}

void fuzhi(int m[], int n[]) {
	for (int i = 0; i < MAXLEN; i++) {
		m[i] = n[i];
	}
}

ostream &operator<<(ostream &cout, int m[]) {
	int top = MAXLEN - 1;
	while (!m[top])
		top--;
	for (; top >= 0; top--) {
		cout << m[top];
	}
	return cout;
}

void chu(int m[], int n) {
	fuzhi(temp, m);
	for (int i = MAXLEN - 1; i > 0; i--) {
		temp[i - 1] += temp[i] % n * 10;
		temp[i] /= n;
	}
	temp[0] /= n;
}

bool cmp(p &a, p &b) {
	return a.zuoshou * a.youshou < b.zuoshou * b.youshou;
}

int main() {
	int n;
	cin >> n;
	p ren[1005];
	for (int i = 0; i <= n; i++) {
		cin >> ren[i].zuoshou >> ren[i].youshou;
	}
	sort(ren + 1, ren + 1 + n, cmp);
	int m[MAXLEN] = {1};
	cheng(m, ren[0].zuoshou);
	int max[MAXLEN] = {0};
	for (int i = 1; i <= n; i++) {
		chu(m, ren[i].youshou);
//         for(int j = 0;j < MAXLEN;j++){
//             temp[j] = m[j];
//         }
//         for(int j = MAXLEN-1;j>0;j--){
//             temp[j-1] = temp[j]%ren[i].youshou*10;
//         }
		if (bijiao(temp, max)) {
			fuzhi(max, temp);
		}
		cheng(m, ren[i].zuoshou);
	}
	cout << max;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值