nenuacm 2019 新生训练#3 题解

以下内容是nenuacm 2019新生训练#3的题解, 代码实现是C++的!

目录

 

A - A + B Problem

B - 发工资咯:)

C - 首字母变大写

D - C语言合法标识符

E - 字符串统计

F - 第几天?

 G - 密码

H - Word Capitalization

I - Football

J - The World

K - The Tower


A - A + B Problem

题解: 直接输出a+b即可,没有坑点,注意多组输入!

#include <cstdio>
using namespace std;

int main()
{
    int a, b;
    while(scanf("%d %d", &a, &b) != EOF){
        printf("%d\n", a+b);
    }
    return 0;
}

B - 发工资咯:)

题解: 对于每个人来说,优先考虑用面值较大的人民币,当当前面值小于较大面值的人民币时再考虑用面值较小的人民币

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

int a[10] = {100, 50, 10, 5, 2, 1};
///可以预先将六种面值的人民币用数组存下
int solve(int x){///对于给定数目的钱,计算出使用人民币最少的张数
    int cnt = 0;
    int num = 0;
    while(x){
        cnt = cnt + x / a[num]; 
        x = x % a[num];
        num ++;
    }
    return cnt;
}
int main()
{
    int n;
    while(scanf("%d", &n) ){
        if(n == 0) break;
        int cnt = 0;
        while(n --){
            int x; scanf("%d", &x);
            cnt += solve(x);
        }
        printf("%d\n", cnt);
    }
    return 0;
}

C - 首字母变大写

题解: 首先注意是按行读入字符串, while(gets(s) != NULL){};其次判断首字母, 一个字母是一个单词的首字母当且仅当是字符串的第一个字母或前面一个字符是空格。

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

char s[110];

int main()
{
    while(gets(s) != NULL){
        int len = strlen(s);
        int flag = 1;
//        printf("len = %d\n", len);
        for(int i = 0; i < len; i ++){
//            printf()
            if(s[i] == ' ') {
                flag = 1; continue;
            }
            if(flag){
                if(s[i] >= 'a' && s[i] <= 'z') s[i] = s[i] - 32;
            }
            flag = 0;
        }
        cout<<s<<endl;
    }
    return 0;
}

D - C语言合法标识符

题解: C语言合法标识符: 仅有由字母、下划线、数字这三个方面组成,但开头必须是字母或下划线。另外,关键字不能是标识符,如main等

注意本题可以不考虑关键字。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char s[1005];
int main()
{
    int T; scanf("%d", &T);
    getchar();
    while(T --){
        int flag = 1;
        gets(s);
        int len = strlen(s);
        if(s[0] != '_' && isalpha(s[0]) == 0){
            ///isalpha(ch) C语言函数判断字符ch是否是字母, 包括大小写字母
            flag = 0;
        }
        for(int i = 1; i < len; i ++){
            ///isalnum(ch) C 语言函数, 判断字符ch是否是数字0~9
            if(isalnum(s[i]) == 0 && isalpha(s[i]) == 0 && s[i] != '_'){
                flag = 0; break;
            }
        }
        if(flag){
            printf("yes\n");
        }
        else {
            printf("no\n");
        }
    }
    return 0;
}

E - 字符串统计

题解: 直接遍历字符串判断当前字符是否是数字字符即可。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char s[1005];
int main()
{
    int T; scanf("%d", &T);
    while(T --){
        scanf("%s", s);
        int len = strlen(s);
        int cnt = 0;
        for(int i = 0; i < len ;i ++){
            if(s[i] >= '0' && s[i] <= '9')cnt ++;
        }
        printf("%d\n", cnt);
    }
    return 0;
}

F - 第几天?

题解: 1、注意闰年在2月会多一天, 闰年的判断条件 能被4整除但不能被100整除 或者直接能被400整除

2、小技巧: 预先用一个数组存一下每个月份的天数

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char s[1005];
int m[15] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool is_leap_year(int x){///判断是否是运年
    if((x % 4 == 0 && x % 100 != 0) || x % 400 == 0) return true;
    return false;
}
int main()
{
    int year, mouth, date;
    while(scanf("%d/%d/%d", &year, &mouth, &date) != EOF){
        int days = 0;
        int flag = 0;
        if(is_leap_year(year)) flag = 1;
        for(int i = 1; i < mouth; i ++){///遍历到统计月份的上一个月
            days += m[i];
        }
        days += date;
        if(mouth > 2) days += flag;
        printf("%d\n", days);
    }
    return 0;
}

 G - 密码

题解: 首先判断给定密码长度是否大于等于8且小于等于16; 其次

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

char s[1005];
char ch[10] = {'~', '!', '@', '#', '$', '%', '^'};///预先存储下第四类字符
bool judge(char c){
    for(int i = 0; i < 7; i++){
        if(c == ch[i]) return true;
    }
    return false;
}
int main()
{
    int T; scanf("%d", &T);
    while(T --){
        scanf("%s", s);
        int len = strlen(s);
        if(len < 8 || len > 16) {
            printf("NO\n"); continue;
        }
        int flag = 1;
        int cnt1 = 0, cnt2 = 0, cnt3 = 0, cnt4 = 0;///表示四类字符, 注意初始化全为 0 
        for(int i = 0; i < len; i ++){
            if(s[i] >= 'A' && s[i] <= 'Z'){
                cnt1 = 1;///第一类字符
            }
            else if(s[i] >= 'a' && s[i] <= 'z'){
                cnt2 = 1;///第二类
            }
            else if(s[i] >= '0' && s[i] <= '9'){
                cnt3 = 1;///第三类
            }
            else if(judge(s[i])) {
                cnt4 = 1;///第四类
            }
            else {
                flag = 0;///前四类都不属于,就是不合法密码
            }
        }
        if(flag == 0){
            printf("NO\n"); continue;
        }
        int cnt = cnt1 + cnt2 + cnt3 + cnt4;
        if(cnt >= 3){
            printf("YES\n");
        }
        else {
            printf("NO\n");
        }

    }
    return 0;
}

H - Word Capitalization

题意: 对于给定的字符串,若首字母是小写则将首字母变成大写,若首字母是大写字母则不变,输出字符串。

题解: 直接判断首字母是否是小写,是则变大写,否咋不变。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char s[1005];
int main()
{
    scanf("%s", s);
    if(s[0] >= 'a' && s[0] <= 'z') s[0] -= 32;
    printf("%s\n", s);
    return 0;
}

I - Football

题意:对于一个阵型, 0表示第一队的人,1表示另一对的人,定义一个危险的阵型,当一个人的后面有7或7个以上的人属于另外一个队的人,判断当前阵型是否是危险阵型?

题解:直接判断是否出现7个或7个以上连续的1或0即可!

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char s[1005];
int main()
{
    scanf("%s", s);
    int len = strlen(s);
    int flag = 0;
    int cnt = 1;
    for(int i = 1; i < len; i ++){
        if(s[i] == s[i-1]){
            if(++ cnt >= 7){
                flag = 1; break;
            }
        }
        else {
            cnt = 1;
        }
    }
    if(flag){
        printf("YES\n");
    }
    else {
        printf("NO\n");
    }
    return 0;
}

J - The World

题意:有四个时区,Beijing(+8时区)、Washington(-5时区)、London(0时区)、Moscow(+3)时区,现在给定A时区的时间,问在此时已A时区为基准下B时区的时间是多少?数据保证A、B时区是以上四个时区中某一个。

题解:注意点 对于时间 12:00AM其实是凌晨0点, 具体实现看代码1!

#include <cstdio>
#include <cstring>
using namespace std;
int h, m; char pm[10];
char s1[100], s2[100];
int getval(char *s){
    /// strcmp(s1, s2) 字符串比较函数, 以字母表的顺序对字符串s1, s2比较大小, 当s1 < s2 时返回-1, 相等时返回0, s1 > s2时返回1
    if(strcmp(s, "Beijing") == 0) return 8;
    if(strcmp(s, "Washington") == 0) return -5;
    if(strcmp(s, "London") == 0) return 0;
    if(strcmp(s, "Moscow") == 0) return 3;
}
void solve(int h, int m){
    ///注意输出时,分钟不足两位要补零
    if(h >= 12){
        if(h == 12){
            printf("%d:%02d PM", h, m);
        }
        else {
            h -= 12;
            printf("%d:%02d PM", h, m);
        }
    }
    else {
        if(h == 0){
            printf("12:%02d AM", m);
        }
        else printf("%d:%02d AM", h, m);
    }
}
int main()
{
    int Case = 0;
    int T;scanf("%d", &T);
    while(T --){
        scanf("%d:%d%s", &h, &m, pm);///时间读入技巧,免除用字符数组读入, 分别表示为 小时、分钟、上下午
        scanf("%s %s", s1, s2);///A、B 时区
        int p1 = getval(s1), p2 = getval(s2);
        if(h == 12) h = 0; ///当h = 12时, 修改为0
        if(pm[0] == 'P') h += 12; ///表明是下午, 将 h 加上12, 转成一天24小时处理
        h += (p2- p1);
        printf("Case %d: ", ++ Case);
        if(h >= 24){///表示已经过了一天,
            printf("Tomorrow ");
            h -= 24;
        }
        else if(h >= 0 && h < 24){///表示还在今天
            printf("Today ");
        }
        else if(h < 0){
            h += 24; 
            printf("Yesterday ");
        }
        solve(h, m);
        printf("\n");
    }
    return 0;
}

K - The Tower

题意: 在平面上放置一个圆锥, 定义了空间坐标,给定圆锥的高与地面半径,现在再圆锥外有一个物体初始位置P0(x0, y0, z0),以速度为\underset{m}{\rightarrow} =(vx,vy,vz)向圆锥方向坠落,问物体与圆锥侧面撞击的时间?

题解:有圆锥曲面的方程  h^{2}(x^{^{2}}+y^{^{2}}) = r^{2}(h-z)^{^{2}}, 物体运动轨迹是一条直线,根据初始位置P0(x0, y0, z0) 以及方向向量(vx, vy, vz)可得直线的参数方程P(x, y, z) = P0 + t * \underset{m}{\rightarrow} = (x0 + t * vx, y0 + t * vy , z0 + t * vz);撞击点就是直线与圆锥曲面的一个交点,将直线参数方程带入圆锥曲面方程求解方程,t的根中满足条件的较小者即输出答案。

#include <cstdio>
#include <cmath>
using namespace std;
#define eps 1e-6
int sgn(double x){
    if(fabs(x) < eps) return 0;
    if(x > 0) return 1;
    return -1;
}
int main()
{
    double r, h;
    double x0, y0, z0, x1, y1, z1;
    int Case = 0;
    int T; scanf("%d", &T);
    while(T --){
        scanf("%lf %lf", &r, &h);
        scanf("%lf %lf %lf %lf %lf %lf", &x0, &y0, &z0, &x1, &y1, &z1);
        double a = (h*h)*(x1*x1 + y1*y1) - (r*r)*(z1*z1);
        double b = (2.0*h*h)*(x0*x1 + y0*y1) + (2.0*r*r)*(h-z0)*z1;
        double c = (h*h)*(x0*x0 + y0*y0) - (r*r)*(h-z0)*(h-z0);
        double delta = b*b - 4.0*a*c;
        
        double t1 = (-b+sqrt(b*b-4.0*a*c))/(2.0*a);
        double t2 = (-b-sqrt(b*b-4.0*a*c))/(2.0*a);
        double t = (sgn(t2) >= 0) ? t2 : t1;
        printf("Case %d: %.6f\n", ++Case, t);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值