ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AtCoder Beginner Contest 258 A - E

2022-07-03 17:34:15  阅读:246  来源: 互联网

标签:AtCoder const Beginner int ll 258 maxn include sum


传送门

这场打的有一种我又行了的感觉

A - When?

向下取整 + 取余

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e17 + 10;

int main()
{
    int x;
    scanf("%d", &x);
    printf("%02d:%02d\n", 21 + x / 60, x % 60);

    return 0;
}

B - Number Box

暴力枚举

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e17 + 10;
string s[20];
int n;
const int xi[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
const int yi[8] = {-1, 0, 1, -1, 1, -1, 0, 1};

ll solve(int x, int y, int k)
{
    ll ans = s[x][y] - '0';
    for(int i=1; i<n; i++)
    {
        x += xi[k];
        y += yi[k];
        x = (x + n) % n;
        y = (y + n) % n;
        ans = ans * 10 + s[x][y] - '0';
    }
    return ans;
}

int main()
{
    cin >> n;
    for(int i=0; i<n; i++) cin >> s[i];
    ll ans = 0;
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            for(int k=0; k<8; k++)
            {
                ans = max(solve(i, j, k), ans);
            }
        }
    }
    cout << ans << endl;
    return 0;
}

C - Rotation

将其看做一个循环的字符串,操作一就是当前指针向后移 x 个位置

操作二就是当前指针的后 x 个位置是啥

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e17 + 10;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, q;
    cin >> n >> q;
    string s;
    cin >> s;
    int tp = 0;
    while(q--)
    {
        int a, b;
        cin >> a >> b;
        if(a == 1) tp = (tp - b + n) % n;
        else
            cout << s[(tp + b - 1 + n) % n] << '\n';
    }
    return 0;
}

D - Trophy

贪心

打游戏的时候都知道,解锁前置关卡,直到打到收益最高的关卡就一直刷副本

因此答案肯定是解锁完前置关卡就不断刷,找到最小值就行

巨大坑:初始值一定要很大很大(不会有人因此 wa 了 3 发吧)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef unsigned long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 4e18 + 10;
ll a[maxn], b[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    ll n, m;
    cin >> n >> m;
    for(int i=0; i<n; i++)
        cin >> a[i] >> b[i];
    ll ans = inf, temp = 0;
    for(int i=0; i<n && m; i++)
    {
        m--;
        temp += a[i] + b[i];
        ans = min(ans, temp + b[i] * m);
    }
    cout << ans << endl;
    return 0;
}

E - Packing Potatoes

二分 + 循环

无限多的物品,模拟是不现实的,考虑从 \(n\) 种物品下手

在第 \(i\) 种物品中,我们可以计算,装满盒子之后需要连续放多少个物品,而且还能知道装完之后是在哪种物品停下来

因此我们考虑建立一条有向边,\(i -> j\) 代表如果当前盒子第一个放入的是第 \(i\) 种物品,则下一个盒子的第一个放入的物品是第 \(j\) 种物品

这样每种物品都会发出一条有向边,总共是 \(n\) 条有向边

不难发现,从第一个物品开始往后跳转,如果这样一直跳转下去的话,会存在一个循环

我们只要对询问的答案,判断一下是否能进入循环,如果不进入,就直接返回答案;如果进入,就取模判断一下最后在循环的哪一步停下来

这样一个无穷大的问题就变成一个循环取模的问题

建立有向边的时候考虑用 前缀和 + 二分 的方式来求,剩下的都是亿点细节问题

细节:

  • 二分的时候,可能会存在 \(n\) 种物品全部取出来都不够装一个盒子的,因此要提前将 \(x\) 对 \(sum\) 取模

  • 求取答案未进入到循环之前,不能进入有向边一个一个找,要提前预处理好进入循环前,第 \(i\) 个盒子是哪一步,不然会 TLE

  • 如果是从 \(1\) 开始的,注意好下标,特别是取模的时候

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e16 + 10;
ll num[maxn], sum[maxn], nex_num[maxn];
int nex[maxn], vis[maxn];
int alp[maxn];

int main()
{
    int n, q, x;
    cin >> n >> q >> x;
    for(int i=1; i<=n; i++)
    {
        cin >> num[i];
        sum[i] = sum[i-1] + num[i];
    }
    ll rx = x / sum[n];
    x %= sum[n];
    for(int i=1; i<=n; i++)
    {
        int way = 0;
        nex_num[i] = rx * n;
        if(sum[n] - sum[i-1] >= x)
        {
            way = lower_bound(sum + 1, sum + 1 + n, x + sum[i-1]) - sum;
            nex_num[i] += way - i + 1;
        }
        else
        {
            way = lower_bound(sum + 1, sum + 1 + n, x - sum[n] + sum[i-1]) - sum;
            nex_num[i] += n - i + 1 + way;
        }
        nex[i] = way + 1;
        if(nex[i] > n) nex[i] = 1;
    }
    int now = 1, dep = 1;
    while(vis[now] == 0)
    {
        vis[now] = dep;
        alp[dep] = now;
        dep++;
        now = nex[now];
    }
    ll pre = vis[now] - 1, rnd = dep - vis[now];
    while(q--)
    {
        ll k;
        cin >> k;
        ll ans = 0;
        if(k <= pre)
            ans = nex_num[alp[k]];
        else
        {
            k -= pre + 1;
            k %= rnd;
            ans = nex_num[alp[k + pre + 1]];
        }
        cout << ans << endl;
    }
    return 0;
}

F - Main Street

基本的思路就是,点到点的最短路径只能是两种方式:

  • 直接走,不走通道

  • 走通道

走通道的做法就考虑必经点,即起点对 4 个方向各发出一条射线,与会最近的通道分别产生 \(4\) 个交点,走通道的最短路必然会经过这四个点的其中一个

同理,终点也能产生四个必经点

走通道的最短路,必然是在这两组点的最短路之间产生,总共 \(16\) 种方式

答案就取最小值就好了

以上均为我的想法,代码实现还没写,有些细节还要处理下

(不鸽,会补题的!)

标签:AtCoder,const,Beginner,int,ll,258,maxn,include,sum
来源: https://www.cnblogs.com/dgsvygd/p/16440285.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有