nenuacm 2019 新生训练#2 题解

说明:以下内容是nenuacm 2019 新生训练#2 的题解,代码实现是纯C语言,仅供新生参考 

目录

A - 求奇数的乘积

B - 平方和与立方和

C - 绝对值排序

D - 求数列的和

E - 三角形

F - 数值统计

G - 统计元音

H - 求平均成绩

I - 查找最大元素

J - Table Tennis

K - Nearly Lucky Number

L - Cheap Travel



A - 求奇数的乘积

题解:O(n)枚举n个数, 当遇到奇数则乘上。

#include <stdio.h>
int main()
{
    int n, x;
    while(scanf("%d", &n) != EOF){
        long long ans = 1;
        while(n --){
            scanf("%d", &x);
            if(x & 1) ans *= x;
        }
        printf("%lld\n", ans);
    }
    return 0;
}

B - 平方和与立方和

题解:ans1记录偶数的平方和, ans2记录奇数的立方和, 枚举从n到m的整数,是偶数则ans1加上其平方, 奇数则ans2加上其立方

#include <stdio.h>
int main()
{
    int n, m, i;
    while(scanf("%d %d", &n, &m) != EOF){
        long long ans1 = 0, ans2 = 0;
        if(n > m){///防止n > m
            int tmp = n; n = m; m = tmp;
        }
        for(i = n; i <= m; i ++){
            if(i & 1)ans2 += i * i * i;
            else ans1 += i * i;
        }
        printf("%lld %lld\n", ans1, ans2);
    }
    return 0;
}

C - 绝对值排序

题解:要学会利用C语言里现有的函数库,调用头文件stdlib.h下的qsort函数, 另外写一个cmp比较函数,具体键代码实现

#include <stdio.h>
#include <stdlib.h>
int Abs(int x){
    if(x < 0) x = -x;
    return x;
}
int cmp(const void*a,const void*b){
    return Abs(*(int*)b) - Abs(*(int*)a);///对绝对值从大到小排序
}
/**
cmp函数通用写法
int cmp(const void *a, const void *b){
    return *(int*)a - *(int*)b; ///按从小到大排序
}
**/
int main()
{
    int n, i;
    int a[110];
    while(scanf("%d", &n) != EOF){
        if(n == 0) break;
        for(i = 0; i < n; i ++) scanf("%d", &a[i]);
        qsort(a, n, sizeof(int), cmp);
        /**
        qsort函数通用写法 qsort(start, n, size, cmp)
        start->待排数组开始位置
        n->表示从start往后n个元素
        size->每个元素所占内存大小
        cmp->比较函数,可定义排序方式
        **/
        for(i = 0; i < n - 1; i ++){
            printf("%d ", a[i]);
        }
        printf("%d\n", a[n-1]);
    }
    return 0;
}

也可自己手动实现排序算法,以选择排序为例:只需修改标条件即可

#include <stdio.h>

int Abs(int x){
    if(x < 0) x = -x;
    return x;
}
void SelectSort(int a[], int n){
    int i, j;
    for(i = 1; i <= n - 1; i ++){
        for(j = i + 1; j <= n; j ++){
            if(Abs(a[i]) < Abs(a[j])){///表明按绝对值从大到小循序排序
                int tmp = a[i]; a[i] = a[j]; a[j] = tmp;
            }
        }
    }
}
int main()
{
    int a[110], i;
    int n;
    while(scanf("%d", &n)){
        if(n == 0) break;
        for(i = 1; i <= n; i ++){
            scanf("%d", &a[i]);
        }
        SelectSort(a, n);
        for(i = 1; i < n; i ++){
            printf("%d ", a[i]);
        }
        printf("%d\n", a[n]);
    }
    return 0;
}

D - 求数列的和

题解:按题意循环m次即可,对于一个数开方需调用头文件math.h下的sqrt()函数, 注意要用浮点型(double即可)数据类型, 保留两位小数输出方法printf("%.2f\n", ans);

#include <stdio.h>
#include <math.h>
int main()
{
    double n;
    int m;
    while(scanf("%lf %d", &n, &m) != EOF){
        double ans = 0;
        while(m --){
            ans += n;
            n = sqrt(n);
        }
        printf("%.2f\n", ans);
    }
    return 0;
}

E - 三角形

题解:判断是否构成三角形,利用三角形的任意两边之和大于第三边,任意两边只差小于第三边的性质,

即判断a+b>c&&b+c>a&&c+a>b是否成立。

注意读入应该是浮点型,因为题目没有说边长一定是整形

#include <stdio.h>
int main()
{
    int T; scanf("%d", &T);
    while(T --){
        double a, b, c; scanf("%lf %lf %lf", &a, &b, &c);
        if(a + b > c && b + c > a && c + a > b){
            printf("YES\n");
        }
        else printf("NO\n");
    }
    return 0;
}

F - 数值统计

题解:定义ans1记录负数个数, ans2记录零的个数, ans3记录整数的个数,注意输入用浮点型数据类型

#include <stdio.h>
#include <math.h>
#define eps 1e-6
int main()
{
    int n;
    while(scanf("%d", &n) != EOF){
        if(n == 0) break;
        int cnt1 = 0, cnt2 = 0, cnt3 = 0;
        while(n --){
            double x; scanf("%lf", &x);
            if(fabs(x) < eps) cnt2 ++;///若x满足此条件,默认x为0
            else if(x < 0) cnt1 ++;
            else if(x > 0) cnt3 ++;
        }
        printf("%d %d %d\n", cnt1, cnt2, cnt3);
    }
    return 0;
}

G - 统计元音

题解:按题意遍历字符数组,当出现元音字母对应个数加一, 注意读入字符串不能用scanf函数,因为输入字符串中间可能有空行,使用gets(s)即可,此函数按行输入字符串

注意输出处理最后一个样例没有空行的小技巧

#include <stdio.h>
#include <string.h>
int main()
{
    char s[110];
    int a[5];
    int Case = 0, i;
    int T; scanf("%d", &T);
    getchar(); ///注意getcha(),没有会很麻烦,不信试试
    while(T --){
        memset(a, 0, sizeof a);
        if(Case) printf("\n");///保证最后一个样例没又多余空行输出
        Case ++;
        gets(s);///按行读入
        int len = strlen(s);
        for(i = 0; i < len; i ++){
            if(s[i] == 'a') a[0] ++;
            else if(s[i] == 'e') a[1] ++;
            else if(s[i] == 'i') a[2] ++;
            else if(s[i] == 'o') a[3] ++;
            else if(s[i] == 'u') a[4] ++;
        }
        printf("a:%d\n", a[0]);
        printf("e:%d\n", a[1]);
        printf("i:%d\n", a[2]);
        printf("o:%d\n", a[3]);
        printf("u:%d\n", a[4]);
    }
    return 0;
}

H - 求平均成绩

题解:对于每个学生的平均成绩和没门科目的平均成绩的统计的方式不一样,前者外存循环应按行遍历,内存循环按列遍历,而后者外层循环应按列遍历,内层循环按行遍历,

#include <stdio.h>
#include <string.h>
int main()
{
    double a[110][6];
    double aver_st[110], aver_cou[6];
    int n, m;
    while(scanf("%d %d", &n, &m) != EOF){
        int i, j;
        /**
            memset(name, val, size)
            此函数是将数组name赋值值为val, 一般用于数组的初始化

        **/
        memset(aver_st, 0, sizeof aver_st);
        memset(aver_cou, 0, sizeof aver_cou);
        for(i = 1; i <= n; i ++){
            for(j = 1; j <= m; j ++){
                scanf("%lf", &a[i][j]);
            }
        }
        /**统计每个学生的平均成绩**/
        for(i = 1; i <= n; i ++){///外层按行遍历
            for(j = 1; j <= m; j ++){///内层按列遍历
                aver_st[i] += a[i][j];
            }
            aver_st[i] /= (1.0 * m);
            printf("%.2f", aver_st[i]);
            if(i == n) printf("\n");
            else printf(" ");
        }
        /**统计没门学科的平均成绩**/
        for(j = 1; j <= m; j ++){///外层按列遍历
            for(i = 1; i <= n; i ++){///内层按行遍历
                aver_cou[j] += a[i][j];
            }
            aver_cou[j] /= (1.0 * n);///的平均分
            printf("%.2f", aver_cou[j]);
            if(j == m) printf("\n");
            else printf(" ");
        }
        int cnt = 0;
        /**统计每门学科的分数都大于等于班级均分的学生个数**/
        for(i = 1; i <= n; i ++){
            int flag = 1;
            for(j = 1; j <= m; j ++){
                if(a[i][j] < aver_cou[j]){
                    flag = 0; break;///当出现有一门学科低于班级均分就跳出循环,并置flag为0
                }
            }
            cnt += flag;
        }
        printf("%d\n\n", cnt);
    }
    return 0;
}

I - 查找最大元素

题解:先O(n)遍历字符串, 用Max记录输入字符串的最大字符,再第二次遍历并输出字符,若当前字符是最大字符,在该字符输出之后多输出(max)

#include <stdio.h>
#include <string.h>
const int maxn = 110;
int max(int a, int b){
    if(a > b) return a;
    return b;
}
int main()
{
    char s[maxn];
    while(scanf("%s", s) != EOF){
        int i, len = strlen(s), Max = -1;
        for(i = 0; i < len; i ++){
            Max = max(Max, (int)s[i]);
        }
        for(i = 0; i < len; i ++){
            printf("%c", s[i]);
            if(Max == (int)s[i]){
                printf("(max)");
            }
        }
        printf("\n");
    }
    return 0;
}

剩下三道题都是CF上的题,英文题面,希望大家习惯,题目难度稍微大一点,重在考察思维

J - Table Tennis

题意:有n个人站成一排进行网球比赛,每个人都有一个能力值,当两个人进行比赛时,能力大的人将会获胜。开始时,第一个人和第二个人进行比赛,赢的人继续与下一个人比赛,战败的人则站到队伍的最后一个人之后,当一个人连续获胜k此时,比赛结束,问:当比赛结束时,获胜的人的能力值是多少? 2<=n<=500, 2<= k <= 1e12, 题目保证每个人的能力值不同,均在1~n之间

题解:本题误解:有人可能认为 获胜的人的能力值就是所有人中能力值最大的,当 k < n 时显然是不成立的,因为能力值最大人可能在后面,比赛还没进行到能力值最大的人就已经结束了。

但当 k >= n 时,其他获胜的人总会遇到能力值最大的人, 能力值最大的人 会一直获胜下去,直至他获胜次数达到k,比赛结束。

当 k < n时, 我们就可以用数组模拟即可,获胜的人继续和下一个人比赛, 而战败的人插入到队伍最后,知道出现第一个连续获胜k次的人为止。 复杂度O(n)

#include <stdio.h>
#include <string.h>

int main()
{
    int a[550*2], cnt, n, i, j;
    long long k;
    scanf("%d %lld", &n, &k);
    int Max = -1;
    for(i = 1; i <= n; i ++){
        scanf("%d", &a[i]); a[i+n] = a[i];
        if(a[i] > Max) Max = a[i];
    }
    if(k >= n) {
        printf("%d\n", Max); return 0;
    }
    int num = 0;
    cnt = 0;///记录连续获胜的次数
    Max = a[1];
    for(i = 2; i <= n + num; i ++){
        if(Max > a[i]){
            cnt ++;
            a[++num] = a[i]; ///战败的人插入到队伍最后
        }
        else {
            a[++num] = Max;  Max = a[i]; ///注意着两条语句不能颠倒
            cnt = 1;
        }
        if(cnt >= k) {
            printf("%d\n", Max); break;
        }
    }
    return 0;
}

K - Nearly Lucky Number

题意:4和7均为幸运数字, 一个数是幸运数当且顶点该数仅包含数字4或7;一个数是近似幸运数当且仅当该数中幸运数字出现的次数之和是幸运数;判定给定一个数n是否是近似幸运数?1<=n<=1e18

可直接考虑用字符数组读入输入的整数,遍历字符串, 统计幸运数字出现的次数记为x,然后判断x是否是幸运数

复杂度O(n)

#include <stdio.h>
#include <string.h>

int main()
{
    int len, i, flag = 1;
    char s[100];scanf("%s", s);
    len = strlen(s);
    int cnt = 0;
    for(i = 0; i < len; i ++){
        if(s[i] == '4' || s[i] == '7') cnt ++;
    }
    if(cnt == 0){///当cnt为0时, 表明输入不包含幸运数字,应输出NO
        printf("NO\n"); return 0;
    }
    while(cnt){
//        printf("cnt = %d\n", cnt);
        if(cnt % 10 != 4 && cnt % 10 != 7){
            flag = 0; break;
        }
        cnt /= 10;
    }
    if(flag){
        printf("YES\n");
    }
    else printf("NO\n");
    return 0;
}

L - Cheap Travel

题意:Ann乘坐地铁,已知一张普通票可以乘坐一站地铁,费用为a元,但Ann可以购买一种特殊的票,Ann可以用此票乘坐m站地铁,花费为b,现在Ann想要乘坐n站地铁,请你帮计算他所需的最小花费

题解:计算特殊票平均每站的花费,将其与乘坐每站的费用a比较,若a或等于则直接购买n张普通票, 答案就是n*a;

否则,Ann可以购买n/m站的特殊票,剩下的n % m 站取 全部购买 普通票和购买一张特殊票的最小值

复杂度O(1)

#include <stdio.h>
int main()
{
    int n, m, a, b;scanf("%d %d %d %d", &n, &m, &a, &b);
    int ans;
    if(m * a <= b){
        ans = n * a;
    }
    else {
        ans = (n / m) * b;
        if((n%m) * a <= b) ans += (n % m) * a;
        else ans += b;
    }
    printf("%d\n", ans);
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值