UPC新生训练赛31场

问题 A: 幸运数字

时间限制: 1.000 Sec  内存限制: 128 MB
提交 状态

题目描述

今年圣诞节,小明收到了很多礼物,每个礼物上都有一个数字,表示对小明的祝福。可 是小明有自己的想法,对小明来说,4 或者 7 的倍数是幸运数字。 现在,小明想要知道所有数字中幸运数字之和是多少?请你帮帮小明!

输入

第一行一个整数n,表示小明收到了n份圣诞礼物。第二行包含n个整数,第i个数a[i]表示第i份礼物上的数字。

输出

输出小明心目中的幸运数字之和。

样例输入 Copy

5
12 13 14 15 16

样例输出 Copy

42

提示

样例解释
小明的幸运数字必须是 4 或者 7 的倍数,这里符合条件的:12+14+16=42
【数据范围】
40%的数据,n<=100,0<a[i]<=100; 
70%的数据,n<=1000,0<a[i]<=10000; 
100%的数据,n<=10000,0<a[i]<=10000000。

#include <iostream>
using namespace std;
int main() {
    int n, a;
    scanf("%d", &n);
    double sum = 0;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a);
        if (a % 7 == 0 || a % 4 == 0) {
            sum += a;
        }
    }
    printf("%.0f", sum);
    return 0;
}

注意数据范围, 不然会报错

问题 B: 对撞

时间限制: 1.000 Sec  内存限制: 128 MB
提交 状态

题目描述

小明发明了一个数字对撞机,两个位数相同的整数可以进行碰撞。碰撞过程中,将两个 整数的每一位进行比较,较小的那个数字会被撞得粉碎,较大的数字保留下来(如果两数 相同,都会保留)。例如下面例子中:

 
两个整数 13570 和 21673 碰撞后,对应数位上较小的值已经消失,碰撞的结果为:第一 个数字剩下 37,第二个数字剩下 2673。 
现在小明想让你写一个程序来显示数字碰撞机的结果,输入两个整数,输出碰撞后的两 个数字。(注意最终结果不能包含多余的前导 0)

输入

第一行一个整数 x,表示输入的第一个整数。 第二行一个整数 y,表示输入的第二个整数。

输出

输出包含两行,第一个表示 x 碰撞后的结果。 第二行表示 y 碰撞后的结果。 若 x 或者 y 所有数位上的数字都消失了,该行输出“BOOM”注意都是大写的。

样例输入 Copy

【样例1】
13570
21673
【样例2】
300
500
【样例3】
1234
5678

样例输出 Copy

【样例1】
37
2673
【样例2】
0
500
【样例3】
BOOM
5678

提示

样例2解释
300第一位被撞碎了,剩下00,因为不能包含前导0,输出0。500没有任何一位被撞碎。
样例3解释
1234每一位都被撞碎了,输出“BOOM”,5678没有任何一位被撞碎。
【数据范围】
对于50%的数据,0≤x,y<10^9
对于80%的数据,0≤x,y<10^100,即x,y的长度不超过100。
对于100%的数据,0≤x,y<=10^1000,即x,y的长度不超过1000。保证所有x和y的位数相同,且x,y本身没有多余的前导0

这个题目我写的比较复杂, 就是自己写一个函数进行两两比较, 然后用这两个数组分别进行判断, 就是一样的再copy一下就好, 定义了flag1 和 flag2来判断零和为空的情况,flag1是判断是否全是0, flag2是用来判断是否全部为空, 也就是boom的情况, flag1 == 0 && flag2 == 0 就输出boom 然后else flag1 == 0 && flag2 != 0也就是全部都是零, 这时候就直接输出零了, 倒也是生了一部分功夫, 不用去除前导零了, 在else就直接输出全部字符(被破坏的我用‘ ’来表示的,这样不耽误输出

代码如下

#include <cstring>
#include <iostream>
using namespace std;
void cmp(char op[], char bp[]) {
    int l1 = strlen(op);
    for (int i = 0; i < l1; i++) {
        if (op[i] - '0' < bp[i] - '0') {
            op[i] = ' ';
        }
        if (op[i] - '0' > bp[i] - '0') {
            bp[i] = ' ';
        }
    }
}
int main() {
    int i, j, k;
    char op[1005], bp[1005];
    scanf("%s", op);
    scanf("%s", bp);
    int len = strlen(op);
    cmp(op, bp);
    // printf("%s\n", op);
    // printf("%s\n", bp);
    int flag1 = 0, flag2 = 0;
    // printf("%d\n", len);
    for (i = 0; i < len; i++) {
        if (op[i] != ' ') {
            flag2 = 1;
        }
        if (op[i] - '0' >= 1) {
            flag1 = 1;
        }
    }
    // cout << flag1 << endl;
    // cout << flag2 << endl;

    if (flag2 == 0 && flag1 == 0) {  //判断为空
        cout << "BOOM" << "\n";
    } else if (flag1 == 0 && flag2 == 1)  //判断为0
        cout << 0 << "\n";
    else {
        i = 0;
        while ((op[i] == '0' || op[i] == ' ' )&& i < len) i++;
        for (; i < len; i++) {
            if (op[i] != ' ') {
                printf("%c", op[i]);
            }
        }
        printf("\n");
    }
    flag1 = flag2 = 0;
    for (i = 0; i < len; i++) {
        if (bp[i] != ' ') {
            flag2 = 1;
        }
        if (bp[i] - '0' >= 1) {
            flag1 = 1;
        }
    }

    if (flag2 == 0 && flag1 == 0) {  //判断为空
        cout << "BOOM" << "\n";
    } else if (flag1 == 0 && flag2 == 1)  //判断为0
        cout << 0 << "\n";
    else {
        i = 0;
        while ((bp[i] == '0' || bp[i] == ' ') && i < len) i++;
        for (; i < len; i++) {
            if (bp[i] != ' ') {
                printf("%c", bp[i]);
            }
        }
        printf("\n");
    }
    return 0;
}

 

问题 C: 差值求和

时间限制: 1.000 Sec  内存限制: 128 MB
提交 状态

题目描述

小明最近学习了差的绝对值,|a-b|表示a-b的绝对值,若a-b>=0,则|a-b|=a-b;若a-b<0,则|a-b|=-(a-b)。
经过几次练习,小明已经熟练掌握了差的绝对值,现在他找来了N个整数,开始任意取出两个数,求差的绝对值,再将所有差的绝对值相加。例如N=4,有4个整数,分别是1,2,3,4。任取两个数有6种取法,|1-2|=1,|1-3|=2,|1-4|=3,|2-3|=1,|2-4|=2,|3-4|=1,它们的和就是10。
由于运算量太大,累坏了小明。请你写一个程序帮他计算一下吧。

输入

第一行一个整数n,表示有n个整数
第二行n个整数,表示小明写下的n个整数

输出

输出一个数,表示任意两数差的绝对值之和。

样例输入 Copy

【样例1】
3
3 1 2
【样例2】
4
1 2 3 4

样例输出 Copy

【样例1】
4
【样例2】
10

提示

样例1解释:|3-1|=2,|3-2|=1,|1-2|=1,答案为4

对于40%的数据,n<=1000,0<=每个数<=1000
对于70%的数据,输入数据保证第二行的n个数字从小到大有序。
对于100%的数据,n<=100000,0<=每个数<=1,000,000,000

我的思路是先排序, 然后用另外一个数组挨个储存相邻两个数的差值。 然后再从大到小遍历相乘

代码

#include <algorithm>
#include <iostream>
using namespace std;
typedef long long int ll;
int main() {
    ios::sync_with_stdio(false);
    ll sum = 0, n, a[100010], b[100010], i, j, k;
    cin >> n;
    for (i = 1; i <= n; i++) {
        cin >> a[i];
    }
    sort(a + 1, a + 1 + n);
    for (i = 2; i <= n; i++) b[i] = a[i] - a[i - 1];
    ll temp = 0;
    ll cnt = 1;
    for (ll i = n; i > 1; i--, cnt++) {
        temp += b[i] * cnt;
        sum += temp;
    }
    cout << sum;
    return 0;
}

这个题, 我也比较迷糊。。。。。

问题 E: 哈夫曼编码

时间限制: 1.000 Sec  内存限制: 128 MB
提交 状态

题目描述

哈夫曼编码是一种编码方式,是可变字长编码的一种,由Huffman于1952年提出。该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫Huffman编码。简单地来说,就是出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的。
现在请你模拟这样的原则对给定的一个字符串进行字母统计。

输入

输入只有一行,是一个字符串,由小写英文字母组成,长度不超过255个字符。

输出

输出有若干行,每行有两部分组成:一个字母和该字母出现的频率,中间用一个空格分隔,并按频率高低排列,频率相同时则按字母的ASC码的先后顺序排列。

样例输入 Copy

soon

样例输出 Copy

o 2
n 1
s 1

我不是很明白为什么用结构体进行排序的时候小范围数据总是容易出错, 但是大数就不会错, 换了个思路就是储存, 然后倒着排序就好了,255是关键。

#include <iostream>
#include <cstring>
using namespace std;
int a[30];
char op[10010];
int main() {
    scanf("%s", op);
    int i, j, k;
    for (i = 0; i < strlen(op); i++) {
        a[op[i]]++;
    }
    for (j = 255; j >= 1; j--) {
        for (i = 'a'; i <= 'z'; i++) {
            if (a[i] == j) {
                printf("%c %d\n", i , j);
            }
        }
    }
    return 0;
}

注意排序的的要求:从大到小, 相同次数就从a到z。

for (j = 255; j >= 1; j--) {
        for (i = 'a'; i <= 'z'; i++) {
            if (a[i] == j) {
                printf("%c %d\n", i , j);
            }
        }
    }

完事。

剩下的题没意义了。。

run了家人们。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值