GPLT团体程序设计天梯赛题解L1部分

最近学习太忙还剩几题没更新

L1-001 Hello World (5 分)

GPLT 最难的一题!!!

#include <bits/stdc++.h>
using namespace std;
int main() {
    cout << "Hello World!";
    return 0;
}

L1-002 打印沙漏 (20 分)

因为图形上下对称,所以可以先计算出上半图形的高度、宽度,这题主要就是考察逻辑思维。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, height = 1, width = 1;
    char ch;
    cin >> n >> ch;
    --n;  // 先扣去最中间的一个字符
    while (true) {
        if (n - 2 * (width + 2) >= 0) {
            ++height;
            width += 2;
            n -= 2 * width;
        } else
            break;
    }
    for (int i = 0; i < height; ++i) {
        for (int j = 0; j < i; ++j) cout << ' ';
        for (int j = 0; j < 2 * height - 1 - 2 * i; ++j) cout << ch;
        cout << '\n';
    }
    for (int i = 0; i < height - 1; ++i) {
        for (int j = 0; j < height - 2 - i; ++j) cout << ' ';
        for (int j = 0; j < 2 * (i + 1) + 1; ++j) cout << ch;
        cout << '\n';
    }
    cout << n;
    return 0;
}

L1-003 个位数统计 (15 分)

虽然题目描述需要输入正整数,但是输入正整数需要一次一次取模才能得到各位,直接以字符串的方式输入就很简单。

#include <bits/stdc++.h>

using namespace std;

int main() {
    int cnt[10] = {0};
    string num;
    cin >> num;
    for (int i = 0; i < num.size(); ++i) ++cnt[num[i] - '0'];
    for (int i = 0; i < 10; ++i)
        if (cnt[i] > 0) cout << i << ':' << cnt[i] << '\n';
    return 0;
}

L1-004 计算摄氏温度 (5 分)

没有什么难点,L1 很多题都像这样。

#include <bits/stdc++.h>

using namespace std;

int main() {
    int F;
    cin >> F;
    int C = 5 * (F - 32) / 9;
    cout << "Celsius = " << C;
    return 0;
}

L1-005 考试座位号 (15 分)

把试机座位号当作下标,然后准考证号和考试座位号分别存入 a, b 数组,最后输出就好。(准考证号 16 位,int 装不下)

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
LL x, a[1005];
int n, m, y, z, b[1005];

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%lld%d%d", &x, &y, &z);
        a[y] = x;
        b[y] = z;
    }
    scanf("%d", &m);
    for (int i = 0; i < m; ++i) {
        scanf("%d", &y);
        printf("%lld %d\n", a[y], b[y]);
    }
    return 0;
}

L1-006 连续因子 (20 分)

用循环模拟出可能的连续因子序列。需要注意几个优化的地方,for (int i = 2; i <= sqrt(n); ++i),很好理解,大于 sqrt(n) 的数再随便乘一下就大于 n 了,肯定就不是因子,所以这里只走到 sqrt(n)

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
LL n, tmp;
int start, len;

int main() {
    scanf("%lld", &n);
    for (int i = 2; i <= sqrt(n); ++i) {
        tmp = 1;
        for (int j = i; tmp * j <= n; ++j) {
            tmp *= j;
            if (n % tmp) break;  // 如果tmp不是n的因子,再乘任何数也不是
            if (j - i + 1 > len) {
                start = i;
                len = j - i + 1;
            }
        }
    }
    if (!start) {
        start = n;
        len = 1;
    }
    printf("%d\n%d", len, start);
    for (int i = 1; i < len; ++i) printf("*%d", start + i);
    return 0;
}

L1-007 念数字 (10 分)

只要注意行尾不能有空格就好了。

#include <bits/stdc++.h>

using namespace std;

string a[] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};

int main() {
    string s;
    cin >> s;
    if (s[0] == '-')
        cout << "fu";
    else
        cout << a[s[0] - '0'];
    for (int i = 1; i < s.size(); ++i)
        cout << ' ' << a[s[i] - '0'];
    return 0;
}

L1-008 求整数段和 (10 分)

只能说 GPLT 的题太细节了,不难的一题但是正确率很低,因为很容易出现刚好 5 个数时,最后连换两行的情况。

#include <bits/stdc++.h>

using namespace std;

int main() {
    int a, b, sum = 0;
    scanf("%d%d", &a, &b);
    for (int i = a; i <= b; ++i) {
        sum += i;
        printf("%5d", i);
        if ((i - a + 1) % 5 == 0)
            printf("\n");
        else if (i == b)
            printf("\n");
    }
    printf("Sum = %d", sum);
    return 0;
}

L1-009 N 个数求和 (20 分)

分数求和,难点就是通分,需要求最大公约数,可以用欧几里得算法(gcd)求得。最后还有一点需要注意,测试数据是在长整型范围内的。

#include <bits/stdc++.h>
typedef long long LL;
using namespace std;

LL gcd(LL a, LL b) { return b == 0 ? a : gcd(b, a % b); }

int main() {
    char c;
    int n;
    LL x, y, tmp;
    cin >> n;
    cin >> x >> c >> y;
    LL sx = x, sy = y;
    for (int i = 1; i < n; ++i) {
        cin >> x >> c >> y;
        tmp = sy / gcd(sy, y) * y;
        sx = sx * (tmp / sy) + x * (tmp / y);
        sy = tmp;
    }
    LL num = sx / sy;
    sx %= sy;
    tmp = gcd(sx, sy);
    sx /= tmp;
    sy /= tmp;
    if (sx == 0)
        cout << num;
    else if (num == 0)
        cout << sx << '/' << sy;
    else
        cout << abs(num) << ' ' << sx << '/' << sy;
    return 0;
}

L1-010 比较大小 (10 分)

简单的排序。

#include <bits/stdc++.h>

using namespace std;

int main() {
    int a[3];
    for (int i = 0; i < 3; ++i)
        cin >> a[i];
    sort(a, a + 3);
    cout << a[0] << "->" << a[1] << "->" << a[2];
    return 0;
}

L1-011 A-B (20 分)

字符串,查找,删除。

#include <bits/stdc++.h>

using namespace std;

int main() {
    string a, b;
    getline(cin, a);
    getline(cin, b);
    for (int i = 0; i < b.size();) {
        if (a.find(b[i]) != -1)
            a.erase(a.find(b[i]), 1);
        else
            ++i;
    }
    cout << a;
    return 0;
}

L1-012 计算指数 (5 分)

水题。

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    cout << "2^" << n << " = " << pow(2, n);
    return 0;
}

L1-013 计算阶乘和 (10 分)

水题。

#include <bits/stdc++.h>
using namespace std;

int fac(int x) { return x == 1 ? 1 : fac(x - 1) * x; }

int main() {
    int n, sum = 0;
    cin >> n;
    for (int i = 1; i <= n; ++i)
        sum += fac(i);
    cout << sum;
    return 0;
}

L1-014 简单题 (5 分)

水题。

#include <iostream>
using namespace std;
int main() {
    cout << "This is a simple problem.";
    return 0;
}

L1-015 跟奥巴马一起画方块 (15 分)

主要就是四舍五入的部分,可以直接用 cmath 里的 round 函数。

#include <bits/stdc++.h>
using namespace std;

int main() {
	int n;
	char c;
	cin >> n >> c;
	int m = round(n * 1.0 / 2);
	for (int i = 0; i < m; ++i) {
		for (int j = 0; j < n; ++j)
			cout << c;
		cout << endl;
	}
	return 0;
}

L1-016 查验身份证 (15 分)

水题,就是麻烦了点。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int a[] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
    int b[] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
    int n;
    cin >> n;
    string s;
    bool flag = false;
    while (n--) {
        int sum = 0;
        cin >> s;
        for (int i = 0; i < s.size() - 1; ++i)
            sum += (s[i] - '0') * a[i];
        sum %= 11;
        if (b[sum] != s.back()) {
            cout << s << endl;
            flag = true;
        }
    }
    if (!flag)
        cout << "All passed";
    return 0;
}

L1-017 到底有多二 (15 分)

用 cout << fixed << setprecision(2) 或 c 语言的 printf 控制小数点位数。

#include <bits/stdc++.h>
using namespace std;

int main() {
    string s;
    cin >> s;
    int cnt = 0;
    double flag = 1;
    if (s[0] == '-') {
        flag *= 1.5;
        s.erase(s.begin(), s.begin() + 1);
    }
    if ((s.back() - '0') % 2 == 0) flag *= 2;
    for (int i = 0; i < s.size(); ++i)
        if (s[i] == '2') ++cnt;
    cout << fixed << setprecision(2)
         << cnt * flag / s.size() * 100 << '%';
    return 0;
}

L1-018 大笨钟 (10 分)

注意 12 点整不需要敲,过了 12 点就要敲。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int h, m;
    scanf("%d:%d", &h, &m);
    if (h >= 0 && h < 12 || h == 12 && m == 0)
        printf("Only %02d:%02d.  Too early to Dang.", h, m);
    else {
        if (m == 0)
            h -= 12;
        else
            h -= 11;
        while (h--)
            printf("Dang");
    }
    return 0;
}

L1-019 谁先倒 (15 分)

假如酒量给的是 1,需要喝 2 杯才能倒,所以输入两人的酒量后,都需要加 1。另外题目描述第二行输入一个正整数 N,实际上 N 根本没用。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, m, _, a, b, c, d;
    int cnt1 = 0, cnt2 = 0;
    cin >> n >> m >> _;
    ++n, ++m;
    while (n && m) {
        cin >> a >> b >> c >> d;
        int tmp = a + c;
        if (b == tmp && d != tmp) {
            --n;
            ++cnt1;
        } else if (b != tmp && d == tmp) {
            --m;
            ++cnt2;
        }
    }
    if (n)
        cout << "B\n" << cnt1;
    else
        cout << "A\n" << cnt2;
    return 0;
}

L1-020 帅到没朋友 (20 分)

朋友圈人数如果为 1,不做处理。大于 1 的话,说明有朋友,做个标记,注意输出格式。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, k, id;
    vector<bool> fri(100000, false), vis(100000, false);
    cin >> n;
    while (n--) {
        cin >> k;
        if (k == 1)
            cin >> id;
        else {
            while (k--) {
                cin >> id;
                fri[id] = true;
            }
        }
    }
    cin >> n;
    bool flag = false;
    while (n--) {
        cin >> id;
        if (!fri[id] && !vis[id]) {
            if (flag) cout << ' ';
            cout << setfill('0') << setw(5) << id;
            vis[id] = flag = true;
        }
    }
    if (!flag) cout << "No one is handsome";
    return 0;
}

L1-021 重要的话说三遍 (5 分)

水题。

#include <bits/stdc++.h>
using namespace std;

int main() {
    cout << "I'm gonna WIN!" << endl;
    cout << "I'm gonna WIN!" << endl;
    cout << "I'm gonna WIN!" << endl;
    return 0;
}

L1-022 奇偶分家 (10 分)

有个小技巧,用按位与运算判断奇偶性是比模运算快的。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, x, a = 0, b = 0;
    cin >> n;
    while (n--) {
        cin >> x;
        if (x & 1)
            ++a;
        else
            ++b;
    }
    cout << a << ' ' << b;
    return 0;
}

L1-023 输出 GPLT (20 分)

遍历一遍字符串,分别统计’G’,’P’,’L’,’T’的个数(大写小写都算),最后用一个 while 循环控制输出就好了。

#include <bits/stdc++.h>
using namespace std;

int main() {
    string str;
    cin >> str;
    int g = 0, p = 0, l = 0, t = 0;
    for (int i = 0; i < str.size(); ++i) {
        if (str[i] == 'g' || str[i] == 'G')
            ++g;
        else if (str[i] == 'p' || str[i] == 'P')
            ++p;
        else if (str[i] == 'l' || str[i] == 'L')
            ++l;
        else if (str[i] == 't' || str[i] == 'T')
            ++t;
    }
    while (g || p || l || t) {
        if (g) {
            cout << 'G';
            --g;
        }
        if (p) {
            cout << 'P';
            --p;
        }
        if (l) {
            cout << 'L';
            --l;
        }
        if (t) {
            cout << 'T';
            --t;
        }
    }
    return 0;
}

L1-024 后天 (5 分)

#include <bits/stdc++.h>
using namespace std;

int main() {
    int d;
    cin >> d;
    cout << (d + 1) % 7 + 1;
    return 0;
}

L1-025 正整数 A+B (15 分)

直接整行读入,然后因为题目描述第一个空格是两个数的分隔,所以按第一个空格的位置分隔开,最后就是简单的字符串转数字。

#include <bits/stdc++.h>
using namespace std;

int getNum(string &s) {
    int num = 0;
    for (int i = 0; i < s.size(); ++i) {
        if (s[i] < '0' || s[i] > '9')
            return -1;
        num = num * 10 + s[i] - '0';
    }
    return (num >= 1 && num <= 1000) ? num : -1;
}

int main() {
    string line, s1, s2;
    getline(cin, line);
    int space = line.find(' ');
    s1 = line.substr(0, space);
    s2 = line.substr(space + 1);
    int n1 = getNum(s1), n2 = getNum(s2);
    if (n1 != -1)
        cout << n1 << " + ";
    else
        cout << "? + ";
    if (n2 != -1)
        cout << n2 << " = ";
    else
        cout << "? = ";
    if (n1 != -1 && n2 != -1)
        cout << n1 + n2;
    else
        cout << '?';
    return 0;
}

L1-026 I Love GPLT (5 分)

真的水啊。

#include <bits/stdc++.h>
using namespace std;

int main() {
    cout << "I\n \nL\no\nv\ne\n \nG\nP\nL\nT";
    return 0;
}

L1-027 出租 (20 分)

vis 数组标记某个数字是否在号码中出现,然后反向遍历一遍把出现的数字放入 v1,同时 mp 映射数字在 v1 中的下标,方便接下来的 v2 数组的获取。

#include <bits/stdc++.h>
using namespace std;

string tel;
bool vis[10];
vector<int> v1, v2;
map<int, int> mp;

int main() {
    cin >> tel;
    for (int i = 0; i < tel.size(); ++i) vis[tel[i] - '0'] = true;
    for (int i = 9; i >= 0; --i) {
        if (vis[i]) {
            mp[i] = v1.size();
            v1.push_back(i);
        }
    }
    for (int i = 0; i < tel.size(); ++i) v2.push_back(mp[tel[i] - '0']);
    cout << "int[] arr = new int[]{";
    for (int i = 0; i < v1.size(); ++i) {
        cout << v1[i];
        if (i != v1.size() - 1) cout << ',';
    }
    cout << "};\nint[] index = new int[]{";
    for (int i = 0; i < v2.size(); ++i) {
        cout << v2[i];
        if (i != v2.size() - 1) cout << ',';
    }
    cout << "};";
    return 0;
}

L1-028 判断素数 (10 分)

水题。

#include <bits/stdc++.h>
using namespace std;

bool isPrime(int x) {
    if (x < 2) return false;
    for (int i = 2; i <= sqrt(x); ++i)
        if (x % i == 0) return false;
    return true;
}

int main() {
    int n, x;
    cin >> n;
    while (n--) {
        cin >> x;
        if (isPrime(x))
            cout << "Yes" << endl;
        else
            cout << "No" << endl;
    }
    return 0;
}

L1-059 敲笨钟 (20 分)

就是几个知识点,getline 前用 cin.get() 吸收回车,然后一些字符串基本操作,find 正向查找,rfind 反向查找,substr 切割。最后就是需要考虑到一种特殊情况,逗号前的字符不足 3 个,那么直接去使用 str.substr(p - 3, 3) == "ong" 判断的话就会出现错误(最后一组测试数据),所以需要加上 p >= 3 这个前提条件。

#include <bits/stdc++.h>

using namespace std;

int main() {
    string str;
    int n;
    cin >> n;
    cin.get();
    while (n--) {
        getline(cin, str);
        int p = str.find(',');
        if (p >= 3 && str.substr(p - 3, 3) == "ong" &&
            str.substr(str.size() - 4, 3) == "ong") {
            p = str.size();
            for (int i = 0; i < 3; ++i) p = str.rfind(' ', p - 1);
            cout << str.substr(0, p) << " qiao ben zhong.\n";
        } else
            cout << "Skipped\n";
    }
    return 0;
}

用 regex 这个东西骚一下:

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    int n;
    string s;
    cin >> n;
    cin.get();
    while (n--) {
        getline(cin, s);
        if (regex_match(s, regex(".*?ong,.*?ong\\.")))
            cout << regex_replace(s, regex("(\\s\\w+){3}\\."), " qiao ben zhong.") << endl;
        else
            cout << "Skipped" << endl;
    }
    return 0;
}
posted @ 2020-03-17 20:56  毛珑珑  阅读(612)  评论(0)    收藏  举报