首页 > 其他分享 >AtCoder Beginner Contest 363 补题记录(A~F)

AtCoder Beginner Contest 363 补题记录(A~F)

时间:2024-07-21 15:56:15浏览次数:10  
标签:AtCoder return Beginner int long ++ 补题 ans --

难度:A < B < C < E ≈ F << D

做题顺序:A -> B -> C -> F -> E -> D

pkTvrdg.png

其实 VP 的时候 perf 还是有 \(2000+\) 的(虽然说 D 炸了),perf 应该是 \(2028\) 左右

A

signed main() {
    int n;
    cin >> n;
    int cnt = 0;
    do {
        ++cnt;
        ++n;
    } while (n % 100);
    cout << cnt << '\n';
    return 0;
}

B

问题即为:两个操作:整体加一,区间求 \(k\) 大。

因为整体加一之后相对的大小关系不会变化所以直接从大到小排序,然后暴力看整体加多少次 \(1\) 之后 \(a_p\ge t\) 即可。

时间复杂度为 \(O(n^2)\)。当然如果只维护一个 \(a_p\) 的值时间复杂度为 \(O(n)\)。

#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 500100;
int l[N];
signed main() {
    int n, t, p;
    cin >> n >> t >> p;
    for (int i = 1; i <= n; ++i)
        scanf("%lld", &l[i]);
    sort(l + 1, l + n + 1, greater<>());
    // 至少有 p 个人头发长度超过为 t
    if (l[p] >= t) {
        puts("0");
        return 0;
    }
    for (int i = 1; ; ++i) {
        for (int j = 1; j <= n; ++j)
            ++l[j];
        if (l[p] >= t) {
            printf("%lld\n", i);
            return 0;
        }
    }
    return 0;
}

C

直接枚举字符串 \(s\) 的所有排列,然后暴力找有没有长度为 \(k\) 的回文字符串即可。记得去重。

枚举字符串所有排列可以先给字符串排序,然后用 next_permutation 找下一个排列。

时间复杂度为 \(O(n!nk)\)。

#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 500100;
int l[N];
signed main() {
    int n, k;
    scanf("%lld%lld", &n, &k);
    set<string> se;
    string s;
    cin >> s;
    sort(s.begin(), s.end());
    do {
        int ok = 1;
        for (int i = 0, j = k - 1; j < n; ++i, ++j) {
            string tmp;
            for (int p = i; p <= j; ++p)
                tmp += s[p];
            string we = tmp;
            reverse(we.begin(), we.end());
            if (we == tmp) {
                ok = 0;
                break;
            }
        }
        if (ok) se.insert(s);
    } while (next_permutation(s.begin(), s.end()));
    cout << se.size() << '\n';
    return 0;
}

D

其实不会做.jpg

有一个很好的搞这一类题的方法:首先打表找一下规律,可以发现,对于一个长度为 \(n\) 的字符串:

  • 若 \(n=1\),则有 \(10\) 个长度为 \(n\) 的回文串。
  • 否则,有 \(9\times 10^{\lceil\frac{n}{2}\rceil}\) 个长度为 \(n\) 的回文字符串。

然后就各种乱七八糟处理就行了。具体是怎么过的我也不知道。

大体上就是说,考虑每一位的贡献,枚举这个位置的答案 \(p\),判断如果后面全选择 \(9\),比他小的回文串的数量是否够用。如果够用了就选择她。时间复杂度不太好分析。

然后就是说这个东西细节特别多,就是看到哪里不太对劲就扯一下,凑过去就行。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int ans = 1;
int n, f[55];
signed main(){
    scanf("%lld", &n);
    if (n == 1) {
        puts("0");
        return 0;
    }
    --n;
    f[1] = 9;
    for (int i = 2; i <= 40; ++i){
        if (i & 1)
            f[i] = f[i - 1] * 10;
        else
            f[i] = f[i - 1];
    }
    int k;
    for (k = 1; ; ++k) {
        if (n > f[k])
            n -= f[k];
        else
            break;
    }
    int wei = k + 1 >> 1;
    for (int i = 1; i <= wei; ++i) {
        int st = (i == 1) ? 1 : 0;
        while (n > f[k] / 9) n -= f[k] / 9, ++st;
        --k, --k;
        if (i == 1) ans = st;
        else ans = ans * 10 + st;
    }
    cout << ans;
    if (k & 1)
        ans /= 10;
    while (ans) {
        printf("%lld", ans % 10);
        ans /= 10;
    }
    puts("");
    return 0;
}

E

又回到了简单题。考虑枚举 \(i\) 的值,容易发现,小岛的某一个部分,若在 \(i\) 时刻沉,则 \(i+1\) 时刻也一定是沉的。

然后考虑维护一下当前所有在边上的地段。对于每一个地段,若在 \(i\) 时刻她第一次沉,则枚举和其四连通的四个格子并将其放到新的边界上。为了快速的找到边界上一个格子是否会沉,可以使用一个堆来维护。

时间复杂度为 \(O(nm\log nm)\)。容易发现每一个地段最多只会入队一次出队一次。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int ans = 1;
int n, f[55];
signed main(){
    scanf("%lld", &n);
    if (n == 1) {
        puts("0");
        return 0;
    }
    --n;
    f[1] = 9;
    for (int i = 2; i <= 40; ++i){
        if (i & 1)
            f[i] = f[i - 1] * 10;
        else
            f[i] = f[i - 1];
    }
    int k;
    for (k = 1; ; ++k) {
        if (n > f[k])
            n -= f[k];
        else
            break;
    }
    int wei = k + 1 >> 1;
    for (int i = 1; i <= wei; ++i) {
        int st = (i == 1) ? 1 : 0;
        while (n > f[k] / 9) n -= f[k] / 9, ++st;
        --k, --k;
        if (i == 1) ans = st;
        else ans = ans * 10 + st;
    }
    cout << ans;
    if (k & 1)
        ans /= 10;
    while (ans) {
        printf("%lld", ans % 10);
        ans /= 10;
    }
    puts("");
    return 0;
}

F

还是简单题。容易发现满足条件的字符串 \(S\) 共有两类:

  • \(S\) 中有偶数个元素。
  • \(S\) 中有奇数个元素。

其中偶数个元素的情况可以归结到奇数个元素的情况中。即在正中间的两个元素之间加一个数字 \(1\) 就可以满足条件。

然后开始暴力搜索。枚举当前剩余的数 \(x\) 的每一个因子 \(d\),记 \(D\) 为 \(d\) 的倒序得到的数。如果 \(d\) 和 \(D\) 都满足条件,并且 \(x\bmod (D\times d)=0\),则 \(D\) 和 \(d\) 都是满足条件的,就可以考虑 \(\frac{x}{D\times d}\) 的子问题了。特殊的,若此时 \(x\) 已经可以满足条件了,则可以直接将 \(x\) 作为中间元素输出。

最后警示一下:有返回值的函数一定要返回。这个【】因为没有返回调试了 20+min

#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 500100;
int l[N];
bool check(int n) {
    string s = to_string(n);
    string t = s;
    reverse(t.begin(), t.end());
    return s == t && !count(s.begin(), s.end(), '0');
}
int mysqrt(int x) {
    int l = 0, r = x + 10, best = -1;
    while (l <= r) {
        int mid = l + r >> 1;
        if ((__int128)(mid) * (__int128)(mid) <= x)
            best = mid, l = mid + 1;
        else
            r = mid - 1;
    }
    return best;
}
vector<int> Div(int x) {
    vector<int> v;
    for (int i = 1; i * i <= x; ++i)
        if (x % i == 0) {
            if (i != 1)
                v.emplace_back(i);
            if (i * i != x && i != 1)
                v.emplace_back(x / i);
        }
    sort(v.begin(), v.end());
    return v;
}
void fun(int x, int you, string qian) {
    // cout << "x = " << x << '\n';
    if (check(x)) {
        // cout << "x = " << x << '\n';
        // cout << "qwq: " << qian << '\n';
        // exit(0);
        // cout << "dbg " << qian << ' ' << you << '\n';
        cout << qian;
        if (x) {
            if (qian.size()) cout << "*";
            cout << x;
            if (qian.size()) cout << "*";
        } else {
            cout << "*";
        }
        reverse(qian.begin(), qian.end());
        cout << qian << '\n';
        exit(0);
    }
    vector<int> dx = Div(x);
    // cout << "qwq: ";
    // for (auto &x : dx) cout << x << ' ';
    // cout << "All = " << x << '\n';
    for (auto &d : dx) {
        string sd = to_string(d);
        reverse(sd.begin(), sd.end());
        if (count(sd.begin(), sd.end(), '0')) continue;
        int dd = 0;
        for (auto &x : sd) dd = dd * 10 + x - '0';
        // cout << "qwq " << d << ' ' << dd << '\n';
        if ((x / d) % dd == 0) {
            int val = x / d / dd;
            string nw = qian;
            if (nw.size()) nw += "*";
            nw += to_string(d);
            fun(val, you, nw);
        }
    }
}
signed main() {
    int n;
    scanf("%lld", &n);
    if (check(n)) {
        printf("%lld\n", n);
        return 0;
    }
    vector<int> div = Div(n);
    fun(n, 0, "");
    // for (auto &d : div)
    //     if (check(d)) {
    //         int rem = n / d;
    //         fun(rem, d, "");
    //     }
    cout << "-1\n";
    return 0;
}

G

待补。

标签:AtCoder,return,Beginner,int,long,++,补题,ans,--
From: https://www.cnblogs.com/yhbqwq/p/18314564

相关文章

  • AtCoder Beginner Contest 363
    A.PilingUp(\(\operatorname{Difficulty}11\))让你求某个数距离最近的一个\(k\times100\)的距离是多少.水.#include<bits/stdc++.h>usingnamespacestd;namespacehdk{ namespacefastio{ voidrule(boolsetting=false){std::ios::sync_with_stdio(setting);} ......
  • Codeforces Round 960 (Div.2) 补题
    A非常容易观察到性质,注意Alice为先手,发现当\(a_{\max}\)的个数为奇数时显然能win,但如果\(a_{\max}\)的个数为偶数且有一个数具有奇数个可以作为跳板,那么也能win,否则就lose。B结论:\(presum_x\geq2+presum_{y-1}\geq2+\min{presum_i}\geq1+\max{presum_i}......
  • Codeforces Round 960 (Div. 2) 补题记录(A~D)
    打的稀烂,但是还是上分了(A考虑对值域做一个后缀和。若某一个后缀和的值是奇数那么先手就可以获胜。否则就不可以获胜。(我才不会告诉你我这题吃了一次罚时的)#pragmaGCCoptimize(3)#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intmysqrt(intx){......
  • 牛客小白月赛98补题
    D一道很典型的区间DP//区间DP典题#include<bits/stdc++.h>usingnamespacestd;#definelllonglongconstintN=520;lln,L,R;strings;llsum0[N],sum1[N];llf[N][N];voidsolve(){cin>>n>>L>>R>>s;s='......
  • CodeForces Round #959 sponsored by NEAR (Div. 1 + Div. 2) 补题记录(A~E)
    简单场.pngA若\(n\timesm=1\)则显然无解。否则因为\(a\)矩阵是一个\(n\timesm\)的排列,所以说只需要让其循环右移一位即可。时间复杂度\(O(nm)\)。#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=500100;inta[233][233];sign......
  • AtCoder Beginner Contest 360 ( A~D)
    A-AHealthyBreakfasthttps://atcoder.jp/contests/abc360/tasks/abc360_a水题题意:只要R在M左侧即可思路:因为只要三位,所以只需要判断R在第一位或M在最后一位,有重复的情况#include<iostream>#include<cmath>#include<algorithm>usingnamespacestd;intmain(){......
  • 杭电多校补题
    1001.循环位移#include<bits/stdc++.h>usingnamespacestd;typedefunsignedlonglongull;constintN=1048580*2;constintP=131;ullp[N],h1[N],h2[N];voidsolve(){stringa,b;cin>>a>>b;intn=a.size()......
  • 2024夏令营提高1模考0718模拟赛(提高1)补题报告
    2024夏令营提高1模考0718模拟赛(提高1)补题报告$$0718模拟赛(提高1)\\补题报告\2024年7月18日\by\\\唐一潇$$一、做题情况第一题比赛$100/100$,赛后通过第二题比赛$0/100$,赛后通过第三题比赛$0/100$,赛后通过第四题比赛$0/100$,赛后通过比......
  • 牛客day1的补题和总结
    C和I是签到题,没什么好说的。从A开始。A读题读了我20分钟,我才把样例弄懂。。这题目比cf阴间一佰倍,主要也是这类题的题面就是麻烦,有时候中文的题面的也能让我写一半回去再读几遍。这个主要就是写太慢了。完全可以更快的,而且这个思路我觉得大部分其实是lhgg帮我出的,我自己的思路......
  • 河南萌新联赛2024第(一)场 补题报告
    小蓝的二进制询问找规律,可以发现把从0开始的十进制数字转化为二进制。每一个二进制位有0或1两种状态。从低到高的第一位以2为周期,第二位以4为周期,第三位以8为周期……也就是说第n位以2^{n}为周期。每个周期都是前一半是0,后一半是1。举例:000001010011100……#inclu......