NEUQ-acm第三次双周赛补题

7-1 打字

题目描述

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

有很多网站教授正确的打字。下图描述了基本原理: 用同一手指按压颜色相同的键。黄色键需要用小指按压,蓝色的用无名指,绿色的用中指,红色的用食指。
NEUQ-acm第三次双周赛补题_第1张图片
另外,左手按键盘的左侧(从左侧的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 if输出全部情况
一个数组保存次数

代码

#include 
using namespace std;
string s;
int num[8];
int main(){
    cin >> s;
    int n = s.length();
    for(int i = 0; i < n; i++){
        if(s[i]=='`' || s[i]=='1' || s[i]=='Q' || s[i]=='A' || s[i]=='Z')  
            num[0]++;
        else if(s[i]=='2' || s[i]=='W' || s[i]=='S' || s[i]=='X')
            num[1]++;
        else if(s[i]=='3' || s[i]=='E' || s[i]=='D' || s[i]=='C')
            num[2]++;
        else if(s[i]=='4' || s[i]=='R' || s[i]=='F' || s[i]=='V' || s[i]=='5' || s[i]=='T' || s[i]=='G' || s[i]=='B')
            num[3]++;
        else if(s[i]=='6' || s[i]=='Y' || s[i]=='H' || s[i]=='N' || s[i]=='7' || s[i]=='U' || s[i]=='J' || s[i]=='M')
            num[4]++;
        else if(s[i]=='8' || s[i]=='I' || s[i]=='K' || s[i]==',')
            num[5]++;
        else if(s[i]=='9' || s[i]=='O' || s[i]=='L' || s[i]=='.')
            num[6]++;
        else if(s[i]=='0' || s[i]=='P' || s[i]==';' || s[i]=='/' || s[i]=='-' || s[i]=='[' || s[i]=='\'' || s[i]=='=' || s[i]==']')
            num[7]++;
    }
    for(int i = 0; i < 8; i++){
        cout << num[i] << endl;
    }
}

7-2 分香肠

题目描述

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

输入格式

两个整数 N ( 1 ≤ N ≤ 1 0 5 ) N(1≤N≤10^5) N(1N105) M ( 1 ≤ M ≤ 1 0 5 ) M(1≤M≤10^5) M(1M105)

输出格式

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

输入样例

2 6

输出样例

4

思路

将香肠想成一根,将这一根切割成M个相等的线段可以得到需要切的数 ( M − 1 ) (M-1) M1
若切断点在原本就分开的地方,那么就可以少切一刀

代码

#include 
using namespace std;
int n, m;
int main(){
    cin >> n >> m;
    int ans = m;
    double cnt = n*1.0/m;
    double now=0;
    for(int i = 0; i < m; i++){
        now+=cnt;
        if(abs(floor(now+0.5)-now)<=1e-7) ans--;
    }
    cout << ans;
}

困难点:怎么判断是否为整数(不用切的地方)
f l o o r ( n o w + 0.5 ) = = n o w floor(now+0.5)==now floor(now+0.5)==now
注意点:double精度的问题
所以判断是否相等应该写为 a b s ( f l o o r ( n o w + 0.5 ) − n o w ) < = 1 e − 7 abs(floor(now+0.5)-now)<=1e-7 abs(floor(now+0.5)now)<=1e7

7-3 h0145. 会议安排

题目描述

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

输入格式

第一行是一个整型数m(m<100)表示共有m组测试数据。
每组测试数据的第一行是一个整数n(1 随后的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

思路

贪心:按开始时间最早排序,在已选时间 t t t内选结束时间最早的,,并更新时间 t t t

代码

#include 
using namespace std;
int m, n;
int ans;
struct pla{
    int s, f;
    bool operator< (pla b){
        return s < b.s;
    }
}T[10005];
int main(){
    cin >> m;
    for(int i = 0; i < m; i++){
        cin >> n;
        int t=0;
        for(int j = 0; j < n; j++){
            cin >> T[j].s >> T[j].f;
        }
        sort(T, T+n);
        t=T[0].f;
        ans=1;
        for(int i = 1; i < n; i++){
            //cout << T[i].s << " " ;
            if(T[i].s >= t){
                ans++;
                t=T[i].f;
            }
            else if (T[i].f < t){
                t = T[i].f;
            }
        }
        cout << ans << endl;
    }
}

7-4 神秘密码

题目描述

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

输入格式

一个字符串。

输出格式

一个字符串。

输入样例

AC[3FUN]

输出样例

ACFUNFUNFUN

【数据范围】

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

思路

dfs递归
结束条件:遇到 ’ ] ’ 或者字符串遍历完

  1. 如果遇到 ’ [ ’ 进入递归,解字符串,解出来之后加到最终输出的字符串后
  2. 如果遇到字母,直接加到最终输出的字符串后
  3. 如果遇到’ ] ’ 本次·递归结束

代码

#include 
using namespace std;
string dfs(){
    string s,ans;
    char c;
    while(cin >> c){
        if(c == '['){
            int num;
            cin >> num;
            s = dfs();
            while(num--){
                ans += s;
            }
        }
        else if(c == ']') return ans;
        else ans += c;
    }
    return ans;
}
int main(){
    cout << dfs();
    return 0;
   
}

7-5 h0114.国王游戏

题目描述

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

输入格式

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

输出格式

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

输入样例

3
1 1
2 3
7 4
4 6

输出样例

2

思路

参考题解:
NEUQ-acm第三次双周赛补题_第2张图片
NEUQ-acm第三次双周赛补题_第3张图片
难点:高精度度乘除及比较

思路

#include 
using namespace std;
const int Max = 1e5+5;
int n;
int a[Max],b[Max];
int lena, lenb, lenans;
int ans[1000005];
struct da{
    long long l,r;
    bool operator<(da b){
        return l*r<b.l*b.r;
    }
}d[1005];
//***************************
//涉及高精度:
void multi(long long num){  //高精度乘
    int x = 0;
    for(int i = 1; i <= lena; i++){
        a[i] = a[i]*num + x;
        x = a[i]/10;
        a[i]%=10;
    }
    while(x){
        a[++lena]=x%10;
        x/=10;
    }
}

void div(long long num){  //高精度除
    int n = lena;
    int now=0;
    while(n > 0){
        now = now*10 + a[n];
        b[n] = now / num;
        now = now % num;
        n--;
    }
    lenb = lena;
    while(b[lenb]==0 && lenb) lenb--;
}

void cmp1(){  //高精度比较
    int flag = 0;
    if(lenans < lenb) flag=1;
    if(lenans == lenb){
        for(int i = lenb; i >= 1; i--){
            if(b[i]>ans[i]){
                flag = 1;
                break;
            }
            if(ans[i]>b[i]) break;
        }
    }
    if(flag==1){
        for(int i = lenb; i >= 1; i--){
            ans[i] = b[i];
        }
        lenans = lenb;
    }
}

int main(){
    cin >> n;
    cin >> d[0].l >> d[0].r;
    for(int i = 1; i <= n; i++){
        cin >> d[i].l >> d[i].r;
    }
    sort(d+1, d+n+1);
    int hl = d[0].l;
    while(hl){  //初始化乘积,即下述long long x
        a[++lena]=hl%10;
        hl /= 10;
    }
    //long long x=d[0].l;
    //long long ans=0;
    for(int i = 1; i <= n; i++){
        //if(x/d[i].r>ans) ans = x/d[i].r;
        //x*=d[i].l;
        div(d[i].r);
        cmp1();
        multi(d[i].l);
    }
    for(int i = lenans; i >= 1; i--){
        cout << ans[i];
    }
}

你可能感兴趣的:(ACM预备队训练,算法,贪心算法,c++)