ACM—TC 联合招新赛1题解

本场题目难度较上场有所增加,思维量较大,但是涉及的知识点都已经提及(都可写。

A.签到题

难度指数:3

这题我本来想放在上一场当防AK题,但是觉得太简单了又放这场当篇难题了。

解题思路:首先简化问题,如果没有单人皮划艇,显然是将所有人按体重排序,从前往后两两结合最优。题目多了两个单人皮划艇,相等于可以去除两个人,数据范围非常小,只需枚举这两个人即可。

新知识点:

AC代码:

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

int n, a[110];
int main()
{
    while (~scanf("%d", &n))
    {
        n *= 2;
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        sort(a + 1, a + 1 + n);
        int ans = 0x3f3f3f3f; 
        for (int i1 = 1; i1 <= n; i1++)
            for (int i2 = i1 + 1; i2 <= n; i2++)
            {
                int sum = 0, ff = 0, fir = 0;
                for (int i = 1; i <= n; i++)
                {
                    if (i == i1 || i == i2)
                        continue;
                    ff++; //ff的奇/偶表示这是双人皮划艇上的前/后一个人
                    if (ff % 2 == 0)
                        sum += a[i] - fir;
                    else
                        fir = a[i];
                }
                ans = min(ans, sum); //取最小方案
            }
        printf("%d\n", ans);
    }
    return 0;
}

B.别看了,从这往下的题都没法做

难度指数:3

解题思路:事实上,只有字符R、起点、终点才是我们会落脚的地方。我们要从起点经过若干个字符R到达终点,那么只需计算每个落脚点之间的距离 D I S i DIS_i DISi,使用最大的 D I S k DIS_k DISk作为第一次跳跃的距离就可以到达终点。

AC代码:

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

char s[100010];
int main()
{
    int t;
    for (scanf("%d", &t); t; t--)
    {
        scanf("%s", s + 1);
        int len = strlen(s + 1);
        int ans = 0, pre = 0;
        for (int i = 1; i <= len; i++)
            if (s[i] == 'R')
            {
                ans = max(ans, i - pre);
                pre = i;
            }
        ans = max(len + 1 - pre, ans);
        printf("%d\n", ans);
    }
    return 0;
}

C.吃糖果啦

难度指数:1.001

看没人写出来的份上加个0.001

解题思路:刚开始第 i i i糖果有 i i i颗糖,第 j j j次你可以选择一袋糖果,在其他糖果袋中加入 j j j颗糖。

ps:多种解要求字典序最小,可观察样例,初始时有1 、2两袋糖果,此时有两种解法:

第一种

1
2

第二种

2
1 2

第二种的12字典序小于2。

综上所述,显然只需要输出

n
1 2 3 ... n

即可。

新知识点:

AC代码:

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

int main()
{
    int t;
    for (scanf("%d", &t); t; t--)
    {
        int n;
        scanf("%d", &n);
        printf("%d\n", n);
        for (int i = 1; i < n; i++)
            printf("%d ", i);
        printf("%d\n", n); //控制行末空格
    }
    return 0;
}

D.上课不摸鱼的lyj

难度指数:4.5

构造题,一般来说这种题都会有一种通解,也就是按某种规律构造,解决这种问题,我们只需找到构造通解的规律即可。

解题思路:找规律。观察第二个样例。前三个数是1到n,后三个数也是1到n的排列,我们可以大胆猜想,只需2n的数就可以构造出正确答案,并且前n个数是1到n。对于后三个数132则可以有很多猜想。

例如:

1 n 2 n-1 3 n-2
1 3 5 7... 2 4 6 8...

验证一下n=5,使用猜想二构造时答案正确,并且这种构造字典序十分小,这时候就可以交一发加以验证

AC代码:

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

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        printf("%d ", i);
    for (int i = 1; i <= n; i += 2)
        printf("%d ", i);
    for (int i = 2; i <= n; i += 2)
        printf("%d ", i);
    return 0;
}

E.你会找关键词吗?

难度指数:2.5

没什么好说的,模拟题,注意细节即可。

AC代码:

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

char a[110];

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%s", a);
        int len = strlen(a), sum = 0, res = 0, ff = 0;
        for (int i = 0; i <= len; i++) //这里要枚举i到len,因为可能以数字结尾
        {
            if (a[i] >= '0' && a[i] <= '9' && !ff) //如果是第一个数字
            {
                res = a[i] - '0';
                ff = 1;
            }
            else if (a[i] >= '0' && a[i] <= '9' && ff) //如果是数字但不是第一个
            {
                res = res * 10 + a[i] - '0';
            }
            else //不是数字
                ff = 0, sum += res, res = 0;
        }
        printf("%d\n", sum);
    }
    return 0;
}

F.艰巨任务

难度指数:2

结构体水题。

AC代码:

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

struct student
{
    int num, c, m, e, s;
} s[310];

bool cmp(student a, student b)
{
    if (a.s == b.s)
    {
        if (a.c == b.c)
        {
            return a.num < b.num;
        }
        return a.c > b.c;
    }
    return a.s > b.s;
}
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d %d %d", &s[i].c, &s[i].m, &s[i].e);
        s[i].num = i;
        s[i].s = s[i].c + s[i].m + s[i].e;
    }
    sort(s + 1, s + 1 + n, cmp);
    for (int i = 1; i <= 5; i++)
        printf("%d %d\n", s[i].num, s[i].s);
    return 0;
}

G.今天你步道乐跑了吗?

难度指数:4.7

预处理出答案,最后O1(一次性)查询

新知识点:三维数组

AC代码:

#include <iostream>
using namespace std;

int MONTH[15] = {0, 31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
void GetFebruary(int y)//闰年 二月份29天 平年28天
{
    if (y % 400 == 0 || (y % 4 == 0 && y % 100))
        MONTH[2] = 29;
    else
        MONTH[2] = 28;
}
int y = 1900, m = 1, d = 1, nd;
int y2 = 2020, m2 = 12, d2 = 13;
int sum[2030][13][33];//sum[i][j][k]表示i年j月k日开始总共还可以跑多少天

void pre()
{
    int week = 0;
    while (y2 != y || m2 != m || d2 != d)
    {
        int prey2 = y2, prem2 = m2, pred2 = d2;
        GetFebruary(y2);
        --d2, week = (week + 1) % 7;
        if (d2 == 0)
        {
            --m2;
            if (m2 == 0)
            {
                m2 = 12;
                --y2;
            }
            d2 = MONTH[m2];
        }
        sum[y2][m2][d2] = sum[prey2][prem2][pred2];
        if (week != 0 && week != 1)
            sum[y2][m2][d2]++;
    }
}
int main()
{
    pre(); //预处理
    while (~scanf("%d-%d-%d %d", &y, &m, &d, &nd) && nd)
    {
        printf("%s", (sum[y][m][d] >= nd ? "huahua yyds\n" : "~~~>_<~~~\n"));
    }
    return 0;
}

H.防AK题

难度指数:0.00001

无 fa ke 说

AC代码:

#include <iostream>
using namespace std;

int main()
{
    int n;
    for (scanf("%d", &n); n; n--)
        printf("I will make a progress!!!\n");
    return 0;
}

I.BET

难度指数:4.4

平局和输都算赢。

AC代码:

#include <iostream>
using namespace std;

int main()
{
    int n, x, y, z, a, b, c;
    scanf("%d%d%d%d%d%d%d", &n, &x, &y, &z, &a, &b, &c);
    int ans1 = n - min(x, a + c) - min(y, b + a) - min(z, b + c);
    int ans2 = min(x, b) + min(y, c) + min(z, a);
    printf("%d %d\n", ans1, ans2);
    return 0;
}

J.Goldbach conjecture

难度指数:2.8

三重枚举会时间超限,枚举 i 、 j i、j ij,第三个数就是 n − i − j n-i-j nij

AC代码:

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

bool f(long long x) //判断素数
{
    if (x <= 1)
        return 0;
    for (long long i = 2; i * i <= x; i++)
        if (x % i == 0)
            return 0;
    return 1;
}
int main()
{
    long long n;
    cin >> n;
    for (int i = 2; i <= n; i++)
        if (f(i))
            for (int j = 2; i + j <= n - 2; j++)
                if (f(j) && f(n - i - j))
                    return printf("%d %d %d\n", i, j, n - i - j), 0;
    return 0;
}
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hesorchen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值