AtCoder Beginner Contest 300

这篇具有很好参考价值的文章主要介绍了AtCoder Beginner Contest 300。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

A - N-choice question (abc300 a)

题目大意

给定一个元素互不相同的数组\(c\)\(a,b\),找到 \(i\)使得 \(c_i = a + b\)

解题思路

直接for循环寻找即可。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    int n, a, b;
    cin >> n >> a >> b;
    for(int i = 0; i < n; ++ i){
        int c;
        cin >> c;
        if (c == a + b){
            cout << i + 1 << '\n';
            return 0;
        }
    }

    return 0;
}



B - Same Map in the RPG World (abc300 b)

题目大意

给定两个矩阵\(A,B\),问能否对 \(A\)进行若干次变换操作得到 \(B\)

变换分两种,一种是将第一列放到最后一列,另一种是将第一行放到最后一行。

解题思路

范围不大,直接枚举所有变换操作判断即可。

如果我们将左右连通,上下连通,那么变换操作实际上不改变每个点的上下左右点。即变换操作可以看成将矩形左上角的点移动。

时间复杂度为\(O(H^2W^2)\)

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    int h, w;
    cin >> h >> w;
    vector<string> a(h), b(h);
    for(auto &i : a){
        cin >> i;
    }
    for(auto &i : b){
        cin >> i;
    }
    auto equal = [&](int x, int y){
        for(int i = 0; i < h; ++ i)
            for(int j = 0; j < w; ++ j){
                int X = (x + i) % h;
                int Y = (y + j) % w;
                if (a[X][Y] != b[i][j]){
                    return false;
                }
            }
        return true;
    };
    auto check = [&](){
        for(int i = 0; i < h; ++ i)
            for(int j = 0; j < w; ++ j)
                if (equal(i, j))
                    return true;
        return false;
    };
    if (check()){
        cout << "Yes" << '\n';
    }
    else 
        cout << "No" << '\n';
    return 0;
}



C - Cross (abc300 c)

题目大意

给定一个包含.#的矩形,问由#组成的形如X的最长长度,每个长度的数量。

解题思路

范围不大,枚举X的位置和大小判断即可。

时间复杂度为\(O(HW\min(HW))\)

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    int h, w;
    cin >> h >> w;
    vector<string> s(h);
    for(auto &i : s)
        cin >> i;
    int sz = min(h, w);
    vector<int> ans(sz + 1);
    auto check = [&](int x, int y){
        if (s[x][y] != '#')
            return 0;
        for(int i = 0; i <= sz; ++ i){
            for(int dx = -1; dx <= 1; dx += 2)
                for(int dy = -1; dy <= 1; dy += 2){
                    int nx = x + i * dx, ny = y + i * dy;
                    if (nx >= h || nx < 0 || ny < 0 || ny >= w)
                        return i - 1;
                    if (s[nx][ny] != '#')
                        return i - 1;
                }
        }
        return sz;
    };
    for(int i = 0; i < h; ++ i)
        for(int j = 0; j < w; ++ j)
            ans[check(i, j)] ++;
    for(int i = 1; i <= sz; ++ i)
        cout << ans[i] << " \n"[i == sz];

    return 0;
}



D - AABCC (abc300 d)

题目大意

\(1 \sim n\)中能表示成 \(a^2 \times b \times c^2(a < b < c)\)\(a,b,c\)为质数的数的个数。

解题思路

由于\(n \leq 10^{12}\),预处理\(1 \to 10^6\)的质数,然后枚举\(c\)\(a\),计算得到乘积小于等于 \(n\)的最大的 \(b\),此时符合条件的数量就是 \(1 \sim b\)中的质数个数,这个事先预处理即可。

时间复杂度是 \(O(\sqrt{n} \log n)\)

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define FOR(i, x, y) for (decay<decltype(y)>::type i = (x), _##i = (y); i < _##i; ++i)
#define FORD(i, x, y) for (decay<decltype(x)>::type i = (x), _##i = (y); i > _##i; --i)

const LL p_max = 1E6 + 100;
LL pr[p_max], p_sz;
int cnt[p_max];
void get_prime() {
    static bool vis[p_max];
    FOR (i, 2, p_max) {
        if (!vis[i]) {
            pr[p_sz++] = i;
            cnt[i] = 1;
        }
        FOR (j, 0, p_sz) {
            if (pr[j] * i >= p_max) break;
            vis[pr[j] * i] = 1;
            if (i % pr[j] == 0) break;
        }
    }
    FOR(i, 2, p_max)
        cnt[i] += cnt[i - 1];
}

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    LL n;
    cin >> n;
    LL ans = 0;
    get_prime();
    for(int i = 0; i < p_sz; ++ i){
        for(int j = 0; j < i; ++ j){
            LL sum = 1ll * pr[i] * pr[i] * pr[j] * pr[j];
            if (sum > n)
                break;
            LL maxb = min(n / sum, pr[i] - 1);
            if (maxb <= pr[j])
                break;
            ans += cnt[maxb] - cnt[pr[j]];
        }
    }
    cout << ans << '\n';

    return 0;
}



E - Dice Product 3 (abc300 e)

题目大意

六面骰子,每面等概率出现。

现在不断掷骰子,直到掷出来的数的乘积大于等于\(N\)

问恰好为 \(N\)的概率。对 \(998244353\)取模。

解题思路

显然\(n\)的质因数只能有 \(2,3,5\)

\(dp[n]\)表示最终是 \(n\)的概率,根据定义, \(dp[n] = \frac{1}{6}dp[\frac{n}{1}] + \frac{1}{6}dp[\frac{n}{2}] + \frac{1}{6}dp[\frac{n}{3}] + \frac{1}{6}dp[\frac{n}{4}] + \frac{1}{6}dp[\frac{n}{5}] + \frac{1}{6}dp[\frac{n}{6}]\),即掷出\(n\)的概率,应当是先掷出 \(\frac{n}{1}\) ,然后再以\(\frac{1}{6}\)的概率掷出 \(1\),或者先掷出 \(\frac{n}{2}\) ,然后再以\(\frac{1}{6}\)的概率掷出 \(2\),依次类推。

当然,如果不整除就没有这部分的概率贡献。

化简一下就是\(dp[n] = \frac{1}{5}dp[\frac{n}{2}] + \frac{1}{5}dp[\frac{n}{3}] + \frac{1}{5}dp[\frac{n}{4}] + \frac{1}{5}dp[\frac{n}{5}] + \frac{1}{5}dp[\frac{n}{6}]\)

因为每次转移状态大小都会除以一个数,所以最终的状态数量应该不会超过\(O(n \log n)\),写个记忆化就可以了。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

const int mo = 998244353;

long long qpower(long long a, long long b){
    long long qwq = 1;
    while(b){
        if (b & 1)
            qwq = qwq * a % mo;
        a = a * a % mo;
        b >>= 1;
    }
    return qwq;
}

long long inv(long long x){
    return qpower(x, mo - 2);
}

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    LL n, ba;
    cin >> n;
    ba = n;
    int cnt2 = 0, cnt3 = 0, cnt5 = 0;
    while (n % 2 == 0){
        ++ cnt2;
        n /= 2;
    }
    while (n % 3 == 0){
        ++ cnt3;
        n /= 3;
    }
    while (n % 5 == 0){
        ++ cnt5;
        n /= 5;
    }
    if (n != 1)
        cout << 0 << '\n';
    else{
        map<LL, int> cache;
        LL inv5 = inv(5);
        function<LL(LL)> dfs = [&](LL n){
            if (n == 1)
                return 1;
            if (cache.find(n) != cache.end())
                return cache[n];
            LL ans = 0;
            for(int i = 2; i <= 6; ++ i)
                if (n % i == 0){
                    ans = (ans + dfs(n / i));
                    if (ans >= mo)
                        ans -= mo;
                }
            cache[n] = ans * inv5 % mo;
            return cache[n];
        };
        cout << dfs(ba) << '\n';

    }

    return 0;
}



F - More Holidays (abc300 f)

题目大意

给定一个包含xo的字符串\(t\),它由一个长度为\(n\)的串\(s\)重复 \(m\)次拼接得到。要求将恰好 \(k\)x变成o,问连续o的最大长度。

解题思路

x的位置都记录下来,容易发现我们进行变换的x肯定是一组连续的x

我们枚举进行变化的第一个x,然后找到之后的第 \(k\)x,之间的长度取个最大值即可。

虽然这个x\(nm = 10^{14}\)个,但由于串是重复拼接得到的,第二部分的串的 x实际上跟第一个串的情况一致(并且不会更优),因此我们只需要枚举第一个串x和第二个串的第一个x(注意这个情况,会利用第一个串最后一个x和第二个串的第一个x之间的o,可能从第一个串的第一个x更优)。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    int n, m;
    LL k;
    cin >> n >> m >> k;
    string s;
    cin >> s;
    vector<int> pos;
    LL cnt = 0;
    for(int i = 0; i < n; ++ i){
        cnt += (s[i] == 'x');
        if (s[i] == 'x')
            pos.push_back(i);
    }
    LL ans = 0;
    LL la = -1;
    auto solve = [&](int st){
        LL left = pos.size() - st;
        LL minn = min(left, k);
        left = k - minn;
        if (left == 0){
            if (st + k == pos.size()){
                return 1ll * n + pos[0] * (m > 1);
            }else {
                return 1ll * pos[st + k];
            }
        }
        LL shift = left / cnt + 1;
        LL remain = left % cnt;
        if (remain == 0 && shift == m){
            return shift * n;
        }else if (shift > m || shift == m && remain > 0)
            return 0ll;
        else{
            return shift * n + pos[remain];
        }
    };
    for(int i = 0; i < pos.size(); ++ i){
        LL r = solve(i);
        ans = max(ans, r - la - 1);
        la = pos[i];
    }
    if (m > 1){
        m -= 1;
        LL r = solve(0);
        ans = max(ans, n + r - pos.back() - 1);
    }
    cout << ans << '\n';

    return 0;
}


求第\(k\)x可能有些情况要讨论,官方题解采用的二分法就可以以\(\log\)的代价避免这个讨论。

x的数量和串\(s\)的长度是同一个数量级,我们也可以枚举答案的左端点,然后二分找到恰好包含\(k\)x的最右端点,长度取个最大值。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

const LL inf = 1e18;

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    int n, m;
    LL k;
    cin >> n >> m >> k;
    string s;
    cin >> s;
    vector<int> sum(n);
    LL cnt = 0;
    for(int i = 0; i < n; ++ i){
        if (s[i] == 'x'){
            sum[i] = 1;
        }
    }
    partial_sum(sum.begin(), sum.end(), sum.begin());
    LL ans = 0;
    LL la = -1;
    auto count = [&](LL pos){
        LL shift = pos / n, remain = pos % n;
        return shift * sum.back() + sum[remain] * (shift != m);
    };
    auto solve = [&](int st){
        LL l = st, r = 1ll * n * m;
        LL down = st == 0 ? 0 : sum[st - 1];
        while(l + 1 < r){
            LL mid = (l + r) >> 1;
            if (count(mid) - down <= k)
                l = mid;
            else 
                r = mid;
        };
        return r;
    };
    for(int i = 0; i < n; ++ i){
        LL r = solve(i);
        ans = max(ans, r - i);
    }
    cout << ans << '\n';

    return 0;
}



G - P-smooth number (abc300 g)

题目大意

<++>文章来源地址https://www.toymoban.com/news/detail-429406.html

解题思路

<++>

神奇的代码



Ex - Fibonacci: Revisited (abc300 h)

题目大意

<++>

解题思路

<++>

神奇的代码



到了这里,关于AtCoder Beginner Contest 300的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AtCoder Beginner Contest 320

    给定 (a,b) ,输出 (a^b + b^a) 。 因为数不超过 (10) ,可以直接用 pow 计算然后转成 (int) 。不会有精度损失。 神奇的代码 给定一个字符串 (s) ,求长度最长的回文串。 因为长度只有 (100) ,可以直接枚举子串,然后暴力判断是不是回文串(翻转后是否和自身相同),复杂

    2024年02月08日
    浏览(38)
  • AtCoder Beginner Contest 348

    给定 (n) ,输出 (ooxooxoox...) ,长度为 (n) 。 按题意模拟即可。 神奇的代码 给定 (n) 个点,对每个点,求出与其距离最远的点的下标。 (n) 只有 (100) ,对于每个点,花 (O(n)) 遍历每个点最大化距离,时间复杂度为 (O(n^2)) 。 神奇的代码 (n) 个豌豆,每个豌豆有美味值

    2024年04月08日
    浏览(42)
  • AtCoder Beginner Contest 302

    给定怪物的血量 (a) 和你每次攻击扣除的血量 (b) ,问打多少次怪物才会死。 答案即为 (lceil frac{a}{b} rceil = lfloor frac{a + b - 1}{b} rfloor) 神奇的代码 给定一个二维网格,格子上有字母,找到一连串位置,使得其字符串为 (snuke) ,要求这一连串位置俩俩相邻,即有共边或

    2024年02月05日
    浏览(78)
  • AtCoder Beginner Contest 304

    依次给定每个人的姓名和年龄,排成一圈。从年龄最小的人依次输出姓名。 找到年龄最小的,依次输出就好了。 神奇的代码 给定一个数字,如果其超过三位数,则仅保留其最高三位,低位数字全部置为0。 读一个 string ,直接赋值即可。 神奇的代码 给定 (n) 个人的坐标,第

    2024年02月07日
    浏览(39)
  • AtCoder Beginner Contest 329

    劳累一天不该写题,启发式合并都写错了 给定一个字符串,将每个字符输出出来,中间留个空格。 遍历输出即可。 神奇的代码 给定一个数组,找出次大的数。 遍历一下,从非最大的数求一个最大值即可。 神奇的代码 给定一个字符串,问有多少个连续的子串,其由一个字母

    2024年02月05日
    浏览(75)
  • AtCoder Beginner Contest 339

    给一个网址,问它的后缀是多少。 找到最后的\\\'.\\\'的位置,然后输出后面的字符串即可。 python 可以一行。 神奇的代码 二维网格,上下左右相连,左上原点。初始全部为白色,位于原点,面朝上。 进行 (n) 次操作,每次操作,将当前格子颜色黑白反转,然后 如果原来是白色

    2024年02月19日
    浏览(31)
  • AtCoder Beginner Contest 340

    给定等差数列的 首项 、 末项 、 公差 。 输出这个等差数列。 从 首相 依次累加 公差 到 末项 即可。 神奇的代码 依次进行 (Q) 次操作,分两种。 1 x ,将 x 放到数组 (a) 的末尾。 2 k ,输出数组 (a) 的倒数第 (k) 项。 用 vector 模拟即可,操作 2 可快速寻址访问。 神奇的代

    2024年02月19日
    浏览(33)
  • AtCoder Beginner Contest 314

    怎么好多陌生单词 审核怎么这么逆天,半小时还没审完 给定 (pi) 的值以及数 (n) ,要求保留 (n) 位小数输出,不四舍五入。 字符串形式储存然后截取末尾即可。 神奇的代码 (n) 个人玩轮盘赌游戏,简单说就是一个转盘有 (37) 个数字以及一个箭头,箭头会等概率停在某

    2024年02月13日
    浏览(40)
  • AtCoder Beginner Contest 308

    这几天在收拾东西搬家,先附上代码,晚点补上题解 补完了 感觉这次FG都写不太明白 给定八个数,问是否满足以下要求: 不严格升序 每个数在 (100 sim 675) 之间 每个数都是 (25) 的倍数 依次对每个数判断是否符合这三个条件即可。 神奇的代码 高桥吃 (n) 份寿司,寿司分

    2024年02月11日
    浏览(30)
  • AtCoder Beginner Contest 345

    给定一个字符串,问是不是形如 ======...==== 的字符串。 根据长度构造出期望的字符串,再判断是否相等即可。 神奇的代码 给定 (a) ,输出 (lceil frac{a}{10} rceil) 上下取整的转换, (lceil frac{a}{10} rceil = lfloor frac{a + 9}{10} rfloor) 。用下取整即可。 Python 的 // 是下取证,

    2024年03月21日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包