首页 > 其他分享 >AtCoder Beginner Contest 363

AtCoder Beginner Contest 363

时间:2024-07-27 17:39:34浏览次数:6  
标签:AtCoder Beginner ... int auto LL cin using 363

上周去玩了(逃

A - Piling Up (abc363 A)

题目大意

给定分数,问晋级还差多少分。分别到\(100,200,300\)分能晋级。

解题思路

找到第一个大于当前分数的,其差即为答案。

神奇的代码
#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 a;
    cin >> a;
    vector<int> rk{100, 200, 300};
    auto it = upper_bound(rk.begin(), rk.end(), a);
    int ans = *it - a;
    cout << ans << '\n';

    return 0;
}



B - Japanese Cursed Doll (abc363 B)

题目大意

给定\(n\)个人的头发长度,每天会涨\(1\)厘米。问至少经过多少天,有至少\(P\)个人的头发长度至少是\(T\)。

解题思路

由于头发都是一起涨的,将头发长度从长到短排序,当第\(P\)个人的头发涨到\(T\)时,前\(P-1\)个也至少是\(T\)了。所以答案就是第\(P\)个人的头发涨到\(T\)的时间。

神奇的代码
#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, t, p;
    cin >> n >> t >> p;
    vector<int> a(n);
    for (auto& x : a) {
        cin >> x;
    }
    sort(a.begin(), a.end(), greater<int>());
    int ans = max(0, t - a[p - 1]);
    cout << ans << '\n';

    return 0;
}



C - Avoid K Palindrome 2 (abc363 C)

题目大意

给定一个字符串,将字母排序,问有多少种情况,其不存在一个长度为\(k\)的回文串。

解题思路

字符串长度\(n\)只有\(10\),花\(O(10!)\)枚举所有的排列情况,然后花\(O(n)\)枚举子串,再花\(O(k)\)判断是否是回文串即可。时间复杂度是\(O(n!nk)\)

神奇的代码
#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, k;
    string s;
    cin >> n >> k >> s;
    int ans = 0;
    auto ispalindrome = [&](string&& s) -> bool {
        auto t = s;
        reverse(t.begin(), t.end());
        return t == s;
    };
    auto check = [&](string s) -> bool {
        for (int i = 0; i <= n - k; i++) {
            if (ispalindrome(s.substr(i, k))) {
                return false;
            }
        }
        return true;
    };
    sort(s.begin(), s.end());
    do {
        ans += check(s);
    } while (next_permutation(s.begin(), s.end()));
    cout << ans << '\n';

    return 0;
}



D - Palindromic Number (abc363 D)

题目大意

求第\(n\)小的回文数字。

解题思路

观察回文数字,按长度分奇数和偶数两种情况。

  • 1 2 3 4 5 6 7 8 9
  • 11 22 33 44 55 66 77 88 99
  • 101 111 121 131 141 151 ... 191
  • 202 212 222 232 242 252 ... 292
  • ...
  • 909 919 929 939 949 959 ... 999
  • 1001 1111 1221 1331 1441 ... 1991
  • 2002 2112 2222 2332 2442 ... 2992
  • ...
  • 9009 9119 9229 9339 9449 ... 9999

由于是前后是对称的,由于数的比较是从高位比较,我们可以把右半部分的低位忽略,这样就变成

  • 1 2 3 4 5 6 7 8 9
  • 1 2 3 4 5 6 7 8 9
  • 10 11 12 13 14 15 ... 19
  • 20 21 22 23 24 25 ... 29
  • ...
  • 90 91 92 93 94 95 ... 99
  • 10 11 12 13 14 15 ... 19
  • 20 21 22 23 24 25 ... 29
  • ...
  • 90 91 92 93 94 95 ... 99

长度是奇偶循环的,去除右半部分,容易发现它就是

  • 1 2 3 4 5 6 7 8 9
  • 10 11 12 13 14 15 16 17 18 19 ... 90 91 92 93 94 95 96 97 98 99
  • 100 101 .......

每行(即一个长度)多出现一次。而依次每个长度的数量分别是\(9,99,999,9999......\)。

因此通过\(n\),得知道第\(n\)个数的长度,以及是该长度的奇还是偶。如何知道长度,枚举即可,其长度不会超过\(O(\log n)\)。

知道该长度后,就知道该长度有多少个数字\(p\),再通过\(n \geq p\)来判断是偶数情况还是奇数情况,\(n \% p\)就是对应的数了。这里的\(n\)是减去小的长度后的值,即从\(1000\)(如果长度是\(4\))开始数的第几个数。

代码中 s=to_string(n % p + p / 9),其中\(p/9\)是因为数是从\(1000\)开始的,而不是\(0000\)开始。

特判一下\(0\)。

神奇的代码
#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);
    LL n;
    cin >> n;
    if (n == 1) {
        cout << "0\n";
        return 0;
    }
    n -= 2;
    LL p = 9;
    while (n >= 2 * p) {
        n -= 2 * p;
        p *= 10;
    }
    auto s = to_string(n % p + p / 9);
    auto t = s;
    reverse(t.begin(), t.end());
    if (n < p)
        s.pop_back();
    auto ans = s + t;
    cout << ans << '\n';

    return 0;
}



E - Sinking Land (abc363 E)

题目大意

方格岛,四面环海。

给出岛的高度,每年海平面上升\(1\)。

问\(y\)年的每一年,没被淹的岛的数量。

解题思路

起初是四周的岛可能会被淹,称之为危险岛,我们需要比较危险岛的高度和海平面高度。

因为越矮的岛越容易被淹,我们优先比较危险岛的高度最低的,如果被淹了,则会新增一些危险岛,然后继续比较高度最低的,直到没被淹。

因此用优先队列维护这些危险岛的高度,当有新的危险岛被淹时,新增周围变成危险岛的高度,模拟即可。

时间复杂度为\(O(hw\log 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, y;
    cin >> h >> w >> y;
    vector<vector<int>> a(h, vector<int>(w));
    for (auto& i : a)
        for (auto& j : i)
            cin >> j;
    priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>,
                   greater<tuple<int, int, int>>>
        pq;
    vector<vector<int>> vis(h, vector<int>(w, 0));
    auto push = [&](int x, int y) {
        if (x >= 0 && x < h && y >= 0 && y < w && !vis[x][y]) {
            vis[x][y] = 1;
            pq.push({a[x][y], x, y});
        }
    };
    for (int i = 0; i < h; i++) {
        push(i, 0);
        push(i, w - 1);
    }
    for (int i = 0; i < w; i++) {
        push(0, i);
        push(h - 1, i);
    }
    array<int, 4> dx = {0, 0, 1, -1};
    array<int, 4> dy = {1, -1, 0, 0};
    int ans = h * w;
    for (int i = 1; i <= y; i++) {
        while (!pq.empty()) {
            auto [v, x, y] = pq.top();
            if (v <= i) {
                pq.pop();
                ans--;
                for (int j = 0; j < 4; j++) {
                    int nx = x + dx[j];
                    int ny = y + dy[j];
                    push(nx, ny);
                }
            } else {
                break;
            }
        }
        cout << ans << '\n';
    }

    return 0;
}



F - Palindromic Expression (abc363 F)

题目大意

给定\(n\),将\(n\)拆成若干个数相乘的表达式,其中这个表达式是个回文串,且不存在数字\(0\)。

解题思路

考虑朴素搜索,每个表达式的每个乘数必定是\(n\)的因子,因此我们事先预处理出\(n\)的所有因子,分析可知我们只需预处理\(< \sqrt{n}\)的因子即可,大于\(\sqrt{n}\)的因子要么其回文数\(< \sqrt{n}\),要么两个数乘起来会\(> n\)了。

然后就枚举乘数是什么,即枚举\(n\)的因子\(x\),然后求其回文数字\(y\),判断\(x\)和\(xy\)是否都是\(n\)的因子。是的话,则就是\(n = x * \frac{n}{xy} * y\),接下来就是判断\(\frac{n}{xy}\)能否表示成一个回文表达式,这就是一个子问题了,记忆化搜索一下即可。

考虑其复杂度,搜索状态的\(n\)的取值只有因数个,每次搜索枚举因数,因此总的时间复杂度是\(O(\sigma^2(n))\),但实际会远小于这个数。

神奇的代码
#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);
    LL n;
    cin >> n;
    vector<int> fac;
    for (LL i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            fac.push_back(i);
        }
    }
    map<LL, pair<LL, LL>> dp;
    auto rev = [](LL x) {
        string s = to_string(x);
        reverse(s.begin(), s.end());
        return stoll(s);
    };
    auto is_palindromic = [&](LL x) { return x == rev(x); };
    auto is_valid = [&](LL x) {
        return to_string(x).find('0') == string::npos;
    };
    auto dfs = [&](auto dfs, LL n) -> bool {
        if (is_valid(n) && is_palindromic(n))
            return true;
        if (dp.count(n))
            return true;
        for (auto& x : fac) {
            auto y = rev(x);
            if (n % x == 0 && n / x % y == 0 && is_valid(x) && is_valid(y) &&
                dfs(dfs, n / x / y)) {
                dp[n] = {x, y};
                return true;
            }
        }
        return false;
    };
    dfs(dfs, n);
    if (dp.empty() && (!is_valid(n) || !is_palindromic(n)))
        cout << -1 << '\n';
    else {
        string ansl, ansr;
        while (dp.count(n)) {
            auto [x, y] = dp[n];
            ansr = ansr + "*" + to_string(x);
            ansl = to_string(y) + "*" + ansl;
            n /= x;
            n /= y;
        }
        string ans = ansl + to_string(n) + ansr;
        cout << ans << '\n';
    }

    return 0;
}



G - Dynamic Scheduling (abc363 G)

题目大意

给定\(n\)个任务的截止完成时间\(d_i\)和奖励\(p_i\),指如果该任务能在\(d_i\)之前完成,则能获得奖励\(p_i\)。

决定每天完成什么任务,使得奖励最大化。

维护\(q\)次操作,每次操作修改一个任务的\(d_i\)和\(p_i\),修改后求上述答案,修改持久化。

解题思路

<++>

神奇的代码



标签:AtCoder,Beginner,...,int,auto,LL,cin,using,363
From: https://www.cnblogs.com/Lanly/p/18327264

相关文章

  • ABC363
    Alink判断即可。点击查看代码#include<bits/stdc++.h>usingnamespacestd;intr;signedmain(){ cin>>r; if(r<100)cout<<100-r; elseif(r<200)cout<<200-r; elseif(r<300)cout<<300-r; return0; }......
  • [ABC363G] Dynamic Scheduling 与 P4511 [CTSC2015] 日程管理
    思路:对于插入操作,设插入\(\{t,p\}\):若当前\(1\simt\)有空位,那么就放进去。否则,\(1\simt\)是被塞满了的:首先容易想到的是找到\(1\simt\)中贡献最小的那个工作,若贡献比\(p\)还小,可以与之替换掉。但是假了,考虑这样一种情况:在\(1\simt\)外有一个更小的......
  • AtCoder Beginner Contest 360 题解(C-E)
    C-MoveIt题目链接:C-MoveIt题目大意:有\(N\)个盒子和\(N\)个物品编号为\(1-N\),物品\(i\)在盒子\(A_i\)中,重量为\(W_i\),你可以进行一种操作将盒子中的一件物品移动到其他任意盒子中,代价为\(W_i\),求使得所有盒子中只存在一件物品的最小操作代价。题解:贪心,可以发现......
  • AT_abc363_e [ABC363E] Sinking Land Solution
    题目大意:有一座矩形岛屿,被分为\(H\timesW\)的网格,四周与海水接触,给定时间\(Y\)年,最初海平面位于高度\(0\\text{m}\),每年海水上升\(1\\text{m}\),请求出每年未被海水淹没的格子数(高度小于等于海水高度即为淹没)。显然有点类似于广搜的想法,用一个队列存储与海水接触的方......
  • [atcoder utpc2023_p] Priority Queue 3
    PriorityQueue3题意:有一个小根堆和\(1\)~\(n\)个数,以及一个操作序列,+表示\(push\),-表示\(pop\),\(pop\)有\(m\)次,问你有多少种插入顺序使得最后的pop集合与给出的的数字集合\(Y\)相同。首先有个浅显的发现:对于不在\(Y\)集合中的数,可选范围形如一个阶梯,换句话......
  • Solution - Atcoder Xmas2019E Sum of f(n)
    考虑\(F(n)=\sum\limits_{i=1}^nf_i=\sum\limits_{i=1}^n\sum\limits_{p\in\mathbb{P},k\ge1}[p^k|i]=\sum\limits_{p\in\mathbb{P},k\ge1}\lfloor\frac{n}{p^k}\rfloor\)。对于这个\(\lfloor\frac{n}{x}\rfloor\),一个比较经典的想法就是考虑对其......
  • Solution - Atcoder Xmas2019D Sum of (-1)^f(n).md
    对于\(f(i)=(-1)^{\sum\limits_jc_j}(i=\prod\limits_jp_j^{c_j}(p_j\in\mathbb{P}))\),一个比较特殊的值就是在\(i\in\mathbb{P}\)时有\(f(i)=-1\)。于是考虑PowerfulNumber筛,构造积性函数\(g\)使得对于\(i\in\mathbb{P}\)有\(g(p)=f(p)\)且\(g\)易......
  • AtCoder Beginner Contest 363
    AtCoderBeginnerContest363前言只出了三题,被d卡住了,事实上e题应该对我而言更简单,没及时换题。A-PilingUp(atcoder.jp)思路代码#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;intmain(){ios::sync_with_stdio(false);cin.......
  • ABC 363
    ABC363D-PalindromicNumber复盘一下几个细节:最后得到的\(n\)代表的是答案在长度为\(i\)的回文数中排第几,所以最终答案要加上长度更短的\(1\sim9\)是要算的长度奇偶的输出细节长度为\(1\simi\)的回文数个数\(10^{\frac{(i+1)}{2}}\)长度为\(i\)的回文数......
  • AtCoder Beginner Contest 363
    AtCoderBeginnerContest363PilingUp模拟题。点击查看代码#include<bits/stdc++.h>usingnamespacestd;inta;signedmain(){cin>>a;if(a%100!=0){a%=100;cout<<100-a;}else{cout<<100;}retur......