春游6.0 | 2019浙江大学校赛及部分题解(E题 G题 J题)

版权声明:欢迎转载博客(转载时请附上原文链接^_^) https://blog.csdn.net/OneLine_/article/details/89300952

下午两点开始比赛 共四个小时

我们是在浙大OJ上做镜像比赛 (不知道为啥比标准时间晚了十分钟……)

感想:

1.要会板子题,但是也要考虑数据和时间限制、空间限制

【比如 A题 队友说这一看就是板子题 二分图匹配啊 然后开始打板子……】

【结果一直超时 一直超内存…… 到比赛结束也没解决 后来问大佬 暴力就过了 TAT】

2.保持头脑清晰

【今天没划水 因为队友没思路 我做的题目简单】

 3.不要依赖固有思维

【比如 J题 队友读完题目后 说找两个合数 10的18次方数据太大 暴力应该不行吧】

【我后来发现这道题目过题人数很多 觉得应该是个水题 而且是通解】

【不按照题目意思去思考 而是把合数变成了某个数的个数 合理推论两次后 得到了我认为的最优通解……】 

4.坚持不懈= = 

【本来是我理解了G题题意 开始敲代码 大白突然说 我来写这题吧(我想前两题都是我做的 那我休息一下……)】

【大白都已经debug完了 然后说她看错样例了 结果还是我来写T^T 弄清楚如何暴力之后 开始敲代码(大白原来的代码都没用……)】 

【第一下WA的时候 感觉可能是等于 0 的情况没有考虑清楚 再交了两发之后发现区间没有判断是否出界 还好来得及555】

【以下是今天我们交题的过程 最后一分钟AC真的很刺激orz】

以下是部分题解(今天没划水啊~)

(注:题目中的数学公式没法复制 所以选择了截屏

E题思路:

ai 数组表示他需要的,bi 数组表示他拥有的,而高级的可以转换为低级的(即 在高位可以变成低位),从高级向低级遍历,如果不满足ai < = bi ,就直接break,不满足条件,否则就将 (bi - ai)的部分全部转换为更低级的部分。

代码如下:

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

long long a[1005], b[1005];
int main()
{
    int t, x;
    scanf("%d", &t);
    for(int i = 0; i < t; i++)
    {
        scanf("%d", &x);
        bool flag = true;
        for(int j = 0; j < x; j++)
        {
            scanf("%lld", &a[j]);
        }
        for(int j = 0; j < x; j++)
        {
            scanf("%lld", &b[j]);
        }
        for(int j = x - 1; j >= 0; j--)
        {
            if(b[j] > a[j])
                b[j - 1] += b[j] - a[j];
            else
            {
                flag = false;
                break;
            }
        }
        if (flag ==true )printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

J题 题意:

输入 t 组数据,每组数据有一个 n ,求两个合数 x,y,使得 x + n = y

思路:

最开始想的是 n + n = 2n (当 n 不是质数时)

当 n 为质数时可以另外判断

过了两分钟想到了更优解

n + 2n = 3n (n != 1)

n + 9 = 10 (n = 1)

代码如下

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

int main()
{
    int t;
    scanf("%d", &t);
    for(int i = 0; i < t; i++)
    {
        long long n;
        scanf("%lld", &n);
        if (n==1)
            printf("9 10\n");
        else
        printf("%lld %lld\n", 2 * n, 3 * n);
    }
    return 0;
}

 (没错 就是这么短hhh)

G题题意

一个邮递员去送信,给出 t 组数据,每个数据包含 n 个地点坐标和包里最多能装 k 封信,最后一封信送完可以不回邮局(邮局的坐标为 0 ),问邮递员最少需要走多少路才能把信全部送完。

有点贪心的思想

先把所有的信都送了(不考虑不回邮局),离得远的信可以一起送

比如 样例中 是先送 -1 位置的信 需要 2 步(往返一共 2 步),然后送 3 位置的信 需要 6 步,最后送 -3 -4 -5 位置的信(k=3 所以三封信一起送) 需要 10 步,一共需要 18 步 。

此时再去考虑 最左端和最右端 哪一个位置距离 0 更远 (即 比较绝对值大小 这里的情况是所有位置有正有负)很明显是 5 > 3 所以 18 - 5 = 13 一共需要13步……

所有位置全为正和全为负的情况要分开讨论~

代码如下:

#include <iostream>
#include <stdio.h>
#include <bits/stdc++.h>
#include <string.h>
using namespace std;
const long long INF = 0x3f3f3f3f;
long long a[100005];

bool cmp(int a, int b)
{
    return a < b;
}
int main()
{
   // freopen("in.txt", "r", stdin);
    int t, n, k;
    scanf("%d", &t);
    for(int i = 0; i < t; i++)
    {
        long long sum = 0;
        int m=0;
        memset(a,INF,sizeof a);
        scanf("%d%d", &n, &k);
        for(int j = 0; j < n; j++)
        {
            scanf("%lld", &a[j]);
        }
        sort(a, a + n, cmp);
        if(a[0] <= 0 && a[n - 1] >= 0)
        {
             m = 0;
            if(a[m + k] < 0 && (m+k)<n)
            {
                while(a[m + k] < 0&& (m+k)<n)
                {
                    sum += a[m] * (-2);
                    m = m + k;
                }
                sum+=a[m]*(-2);        
            }
            else sum += a[m] * (-2);
            m = n - 1;
            if(a[m - k] >0 &&( m-k>=0))
            {
                while(a[m - k] > 0&&( m-k>=0))
                {
                    sum += a[m] * 2;
                    m = m - k;
                }
                sum += a[m]*2;
            }
            else sum += a[m] * 2;
            int maxx = max(abs(a[0]),a[n-1]);
            sum = sum-maxx;
        }
        else if(a[0] >= 0 && a[n - 1] >= 0)
        {
            m = n - 1;
            if(a[m - k] > 0&&( m-k>=0))
            {
                while(a[m - k] > 0&&( m-k>=0))
                {
                    sum += a[m] * 2;
                    m = m - k;
                }
                sum += a[m]*2;
            }
            else sum += a[m] * 2;
            sum = sum-a[n-1];
        }
        else
        {
            m = 0;
            if(a[m + k] < 0&& (m+k)<n)
            {
                while(a[m + k] < 0&& (m+k)<n)
                {
                    sum += a[m] * (-2);
                    m = m + k;
                }
                sum+=a[m]*(-2);       
            }
            else sum += a[m] * (-2);
            sum = sum+a[0];
        }
        printf("%lld\n", sum);
    }
    return 0;
}

可能队友Alone会把A题补了 

目前就这样啦~

要为ccpc好好准备了(ง •̀_•́)ง

猜你喜欢

转载自blog.csdn.net/OneLine_/article/details/89300952