Panasonic Programming Contest 2022(AtCoder Beginner Contest 273) A~D题解

比赛名称:Panasonic Programming Contest 2022(AtCoder Beginner Contest 273)

A - Recursive Function

由于数据范围很小,直接按照题面写出递归函数调用

AC代码

// Problem: A - A Recursive Function
// Contest: AtCoder - Panasonic Programming Contest 2022(AtCoder Beginner Contest 273)
// URL: https://atcoder.jp/contests/abc273/tasks/abc273_a
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
const int N = 2e5 + 10;
const int MOD = 1e9 + 7;
#define endl '\n'
#define PY puts("Yes")
#define PN puts("No")
ll f(int k)
{
    if (!k)
        return 1;
    return k * f(k - 1);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    cout << f(n);
    return 0;
}

B - Broken Rounding

分析

题目给出一个数 x x x和一个数 k k k,要求我们从 i = 1 i=1 i=1 i = k i=k i=k,每次找到一个尽可能大 1 0 k 10^k 10k的倍数 s s s,使得 ∣ s − x ∣ = y \left\vert s-x \right\vert=y sx=y最小。然后将 s s s的值赋给 x x x

y y y的值只可能从 1 0 i 10^i 10i的倍数离 x x x最近的两个值中产生,我们可以选择一个“向上取整”或者“向下取整”,这里的取整是在 1 0 k 10^k 10k的意义下的。这里给出计算公式,记“向上取整”得到 s 1 s1 s1,“向下取整”得到 s 2 s2 s2

s 1 = ( x / 1 0 k + 1 ) × 1 0 k s1=(x/10^k+1) \times 10^k s1=(x/10k+1)×10k
s 2 = x / 1 0 k × 1 0 k s2=x/10^k \times 10^k s2=x/10k×10k

我们在其中选取一个离 x x x最近的值 s s s然后令 x = s x=s x=s,重复 k k k
为了满足 s s s尽可能大,当 s 1 s1 s1 s 2 s2 s2 x x x的距离相等时,选取较大的值“向上取整”得到的 s 1 s1 s1

AC代码

// Problem: B - Broken Rounding
// Contest: AtCoder - Panasonic Programming Contest 2022(AtCoder Beginner Contest 273)
// URL: https://atcoder.jp/contests/abc273/tasks/abc273_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
const int N = 2e5 + 10;
const int MOD = 1e9 + 7;
#define endl '\n'
#define PY puts("Yes")
#define PN puts("No")
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll x, k;
    cin >> x >> k;
    for (int i = 1; i <= k; i++)
    {
        ll s = pow(10, i);
        ll y;
        if (abs(x / s * s - x) < abs((x / s + 1) * s - x))
            y = x / s * s;
        else
            y = (x / s + 1) * s;
        x = y;
    }
    cout << x;
    return 0;
}

C - (K+1)-th Largest Number

思路

这个题的表述我觉得不是很清楚(还是我理解偏差了?),需要求出的是 1 ∼ n 1\sim n 1n的每个数中序列中大于这个数的不重复的数的个数

一开始我看题目中的样例中给出的解释以为是要求序列中每个数中在序列中比这个数大的不重复的数的个数,所以我就顺着这个思路写下去了。

首先创建一个二元组记录序列中每个数的值和其对应的下标,然后按照数的值排序,这样就可以方便统计出相同的数的个数,然后根据二元组中存储的下标来更新每个数中在序列中比这个数大的不重复的数的个数

这样子就得到了我误解题意以为题目要求的答案,但是我们要求的是序列中大于某定值的不重复的数的个数,所以用一个桶来统计也可以得到答案

但是看了官方题解给出的解释发现还有更简单的做法:

每个数的答案是取决于这个数出现的次数的,因为要求是不同的数所以比它大的数不影响答案,观察样例也可以发现这一点
只需记录每个数出现的次数然后将数从大到小排序就可以得出答案

AC代码

还是给出我在比赛时的代码

// Problem: C - (K+1)-th Largest Number
// Contest: AtCoder - Panasonic Programming Contest 2022(AtCoder Beginner Contest 273)
// URL: https://atcoder.jp/contests/abc273/tasks/abc273_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
const int N = 2e5 + 10;
const int MOD = 1e9 + 7;
#define endl '\n'
#define PY puts("Yes")
#define PN puts("No")
set<int> st;
int ans[N];
int a[N];
int res[N];
map<int, vector<int>> mp;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        int x;
        cin >> x;
        a[i] = x;
        st.insert(x);
        mp[x].emplace_back(i);
    }
    int cnt = 0;
    for (auto it = st.begin(); it != st.end(); ++it)
    {
        // cout << *it << " start: ";
        int y = st.size() - cnt - 1;
        for (int i = 0; i < mp[*it].size(); i++)
        {
            // cout << mp[*it][i] << " ";
            ans[mp[*it][i]] = y;
        }
        // cout << "ans: " << y << endl;
        cnt++;
    }
    // sort(ans,ans+n);
    for (int i = 0; i < n; i++)
        res[ans[i]]++;
    for (int k = 0; k < n; k++)
    {
        cout << res[k] << endl;
    }
    return 0;
}

D - LRUD Instructions

思路

想着用一个二维数组标记来做的一看数据妈呀两个 1 e 9 1e9 1e9
只有压缩存储空间了

使用两个map<int,set<int>>来分别存储行和列的障碍物信息,使用set是因为去重方便且帮我们排好序还有现成的二分查找方法upper_bound
但实际上我用了四个,行和列的情况我针对两个方向分别开了不同的map<int,set<int>>因为我们总要查找比当前行(列)的列(行)大或小的第一个障碍物,但是使用lower_bound只能找到第一个大的障碍物,所以为了找到第一个小的障碍物在对应LU 的情况存储x(y)的倒数,这样子通过upper_bound找出来的那个负数将其转正后就是第一个小于当前位置的障碍物

然后我们将第一个遇到的障碍物的位置和没有遇到障碍物能走到距离做比较后取正确的值,最后再和边界比较

AC代码

// Problem: D - LRUD Instructions
// Contest: AtCoder - Panasonic Programming Contest 2022(AtCoder Beginner Contest 273)
// URL: https://atcoder.jp/contests/abc273/tasks/abc273_d
// Memory Limit: 1024 MB
// Time Limit: 3000 ms

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
const int N = 2e5 + 10;
const int MOD = 1e9 + 7;
#define PY puts("Yes")
#define PN puts("No")
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    map<int, set<int>> row1, row2, col1, col2;
    int h, w, a, b;
    cin >> h >> w >> a >> b;
    int n;
    cin >> n;
    while (n--)
    {
        int x, y;
        cin >> x >> y;
        row1[x].insert(y);
        row2[x].insert(-y);
        col1[y].insert(x);
        col2[y].insert(-x);
    }
    int q;
    cin >> q;
    int x = a, y = b;
    while (q--)
    {
        char od;
        int m;
        cin >> od >> m;
        if (od == 'L')
        {
            auto it = row2[x].upper_bound(-y);
            if (it != row2[x].end())
                y = max(-*(it) + 1, y - m);
            else
                y = y - m;
            y = max(y, 1);
        }
        else if (od == 'R')
        {
            auto it = row1[x].upper_bound(y);
            if (it != row1[x].end())
                y = min(*it - 1, y + m);
            else
                y = y + m;
            y = min(y, w);
        }
        else if (od == 'U')
        {
            auto it = col2[y].upper_bound(-x);
            if (it != col2[y].end())
                x = max(-*(it) + 1, x - m);
            else
                x = x - m;
            x = max(x, 1);
        }
        else if (od == 'D')
        {
            auto it = col1[y].upper_bound(x);
            if (it != col1[y].end())
                x = min(*it - 1, x + m);
            else
                x = x + m;
            x = min(x, h);
        }
        cout << x << " " << y << '\n';
    }
    return 0;
}

先写到这里有空再更后面的题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值