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

AtCoder Beginner Contest 347

时间:2024-03-30 23:44:41浏览次数:53  
标签:AtCoder Beginner int LL cin long 347 tie using

A - Divisible (abc347 A)

题目大意

给定\(n\)个数\(a_i\)以及\(k\),输出是 \(k\)的倍数的\(a_i\)整除以 \(k\)的值。

解题思路

按照题意判断取模和求整除即可。

神奇的代码
#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;
    cin >> n >> k;
    while (n--) {
        int a;
        cin >> a;
        if (a % k == 0)
            cout << a / k << ' ';
    }
    cout << '\n';

    return 0;
}



B - Substring (abc347 B)

题目大意

给定字符串\(s\),问子串种类数。

解题思路

\(|s|\)只有 \(100\),直接 \(O(n^2)\)枚举子串丢进 \(set\)里,答案就是 \(set\)的大小。

长度大的话得后缀自动机。

神奇的代码
#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);
    string s;
    cin >> s;
    set<string> ans;
    for (int i = 0; i < s.size(); ++i)
        for (int j = i; j < s.size(); ++j) {
            ans.insert(s.substr(i, j - i + 1));
        }
    cout << ans.size() << '\n';

    return 0;
}



C - Ideal Holidays (abc347 C)

题目大意

一周前\(a\)天假期,后 \(b\)天工作日。

给定 \(n\)天的安排,问第一个安排定在哪天,使得每个安排都在假期。

解题思路

先让安排日期对\(a+b\)取模,剩下的问题就是, \([0,a+b-1]\)数轴上有一堆点,问能否有一个长度为 \(a\)的区间覆盖了所有点。

枚举覆盖的左端点,看与最右边的点的距离是否超过 \(a\)即可。

注意计算\(a+b+d_i\)会超 \(int\)范围。

神奇的代码
#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, a, b;
    cin >> n >> a >> b;
    LL tot = a + b;
    vector<LL> d;
    for (int i = 0; i < n; i++) {
        int x;
        cin >> x;
        --x;
        x %= tot;
        d.push_back(x);
        d.push_back(x + tot);
    }
    ranges::sort(d);
    LL dis = numeric_limits<LL>::max();
    for (int i = 0; i < n; i++) {
        dis = min(dis, d[i + n - 1] - d[i] + 1);
    }
    if (dis <= a)
        cout << "Yes" << endl;
    else
        cout << "No" << endl;

    return 0;
}



D - Popcount and XOR (abc347 D)

题目大意

给定\(a,b,c\),输出一对 \(x,y\),满足:

  • \(x < 2^{60}, y < 2^{60}\)
  • \(popcount(x) = a\)
  • \(popcount(y) = b\)
  • \(x \oplus y = c\)

\(popcount(x)\)即返回 \(x\)在二进制下\(1\)的个数。 \(\oplus\)是异或。

解题思路

构造题。

假设\(c\)在二进制下 \(1\)的个数为 \(cnt\)。

那么这 \(cnt\)个 \(1\)要分配在 \(x,y\)里。假设分配了 \(l\)个 \(1\)给 \(x\), \(y\)个 \(1\)给 \(y\),其中 \(l+r=cnt\)。

此时 \(x\)还剩下 \(a-l\)个 \(1\), \(y\)还剩下 \(b-r\)个 \(1\)要分配,这些 \(1\)的分配需要在 \(\oplus\)时抵消掉。

所以应有 \(a-l=b-r\)。结合 \(l+r=cnt\)可以解得 \(l,r\)值。

即 \(over=\frac{a+b-cnt}{2}\)是分配给\(x,y\)的 \(1\),以在 \(\oplus\)时抵消。

剩下的\(a-over\)和 \(b-over\)是分配给 \(x,y\),以凑成 \(c\)。

因此就逐位遍历 \(c\),如果是 \(1\),则分配给 \(x\)或 \(y\)(看\(a,b > 0\)),如果是 \(0\),则都分配给 \(x,y\)(如果 \(over > 0)\)。

至于无解条件,一个是 \(a+b < c\),一个是 \(a+b-cnt\)不是偶数,还有的情况难以言说,比如 \(a=60,b=60,cnt=60\),因为限定了\(x < 2^{60},y < 2^{60}\),没有多余的位置分配给用于抵消的 \(1\)。所以就最后再判断一下构造出来符不符合要求。

神奇的代码
#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, b;
    LL c;
    cin >> a >> b >> c;
    int aa = a, bb = b;
    auto popcount = [](LL x) {
        int ret = 0;
        while (x) {
            ret += x & 1;
            x >>= 1;
        }
        return ret;
    };
    int cc = popcount(c);
    if (cc > a + b || ((a + b - cc) & 1)) {
        cout << -1 << '\n';
        return 0;
    }

    int over = (a + b - cc) / 2;
    a -= over;
    b -= over;
    if (a < 0 || b < 0) {
        cout << -1 << '\n';
        return 0;
    }

    LL A = 0, B = 0;
    for (int i = 0; i < 60; i++) {
        if (c & (1LL << i)) {
            if (a) {
                A |= 1LL << i;
                a--;
            } else if (b) {
                B |= 1LL << i;
                b--;
            } else {
                assert(0);
            }
        } else if (over) {
            A |= 1LL << i;
            B |= 1LL << i;
            over--;
        }
    }
    if (popcount(A) != aa || popcount(B) != bb) {
        cout << -1 << '\n';
        return 0;
    }
    cout << A << ' ' << B << '\n';

    return 0;
}



E - Set Add Query (abc347 E)

题目大意

初始\(n\)个 \(0\)的数组\(a_i\)和空集合\(s\)。进行以下 \(q\)次操作。

每次操作给定一个 \(x\),

  • 如果 \(x\)在集合里,移除它,否则放入它。
  • 对于\(j \in s\),\(a_j += |s|\)

解题思路

朴素的模拟的复杂度是\(O(nq)\),考虑在这个过程,每个操作后,都要遍历一下集合里的元素,给数组\(a\)的对应位置相加。

当一个数\(x\)在集合 \(s\)里时,每个操作之后都会对 \(a_x\)作贡献,直到它被移除集合。

每次操作都计算贡献的话,就是朴素的模拟,复杂度上限就是 \(O(nq)\)。要优化,就不能每次操作算贡献了。

注意到一个数 \(x\)做出的贡献是一个连续的操作区间,贡献值就是这个操作区间的 \(|s|\)的和。那我们可以维护一个关于操作顺序的 \(|s|\)的前缀和\(presum\),当 \(x\)被移除时,我们就结算它对 \(a_x\)的贡献:就一个前缀和的相减,这里需要记录下\(x\)何时放入的。

操作结束后,再对还在\(s\)里的元素结算下贡献就好了。

神奇的代码
#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, q;
    cin >> n >> q;
    vector<LL> presum;
    presum.push_back(0);
    set<int> s;
    vector<int> la(n, 0);
    vector<LL> ans(n, 0);
    for (int i = 1; i <= q; ++i) {
        int x;
        cin >> x;
        --x;
        if (s.count(x)) {
            ans[x] += presum[i - 1] - presum[la[x] - 1];
            s.erase(x);
        } else {
            la[x] = i;
            s.insert(x);
        }
        presum.push_back(presum.back() + s.size());
    }
    for (auto& i : s) {
        ans[i] += presum[q] - presum[la[i] - 1];
    }
    for (auto& i : ans) {
        cout << i << ' ';
    }
    cout << '\n';

    return 0;
}



F - Non-overlapping Squares (abc347 F)

题目大意

给定一个\(n \times n\)的网格,问三个不重叠的 \(m \times m\)的网格覆盖,和的最大值。

解题思路

<++>

神奇的代码



G - Grid Coloring 2 (abc347 G)

题目大意

<++>

解题思路

<++>

神奇的代码



标签:AtCoder,Beginner,int,LL,cin,long,347,tie,using
From: https://www.cnblogs.com/Lanly/p/18106252

相关文章

  • AT_abc347_c 题解
    最开始的思路爆炸了我就不写了。先d[i]%=(a+b)。然后,排序,破环为链,相当于存储了下一周。再然后,从\(1\)到\(n\)进行一个循环,若d[i+n-1]-d[i]+1<=a就输出Yes。它的原理是什么?翻译一下上面那个语句,就是“我前一个任务的日期的下一周距离我这个任务的日期小于等于节假日天......
  • ABC347题解
    省流:输+赢D按位分析。既然两个数异或后的结果是\(C\),那就考虑\(C\)中为\(1\)的数中有几个是在\(X\)当中的。假如\(\text{a-popcnt(X)==b-popcnt(Y)}\),那么在\(C\)中为\(0\)的数中随便选\(\text{a-popcnt(x)}\)个即可。注意longlong。codeE假如......
  • AtCoder Beginner Contest 347
    很快做完了AB。然后C就不会做了。随便想了个看似正确的就交了,结果WA*1。后来有交了4发,一发比一发离谱。发现D不难,是一个状态数\(60\times60\times60\)的DP,但是貌似细节很多。写了大约20分钟后无伤过了,发现压根没有需要处理的细节。这时是57min。读完E......
  • ABC347G题解
    我不会,但是我会退火!第一眼,\(n\le20\)。退火,启动!大致思路就是随机选一个初始为0的数置为\(1\sim5\)中的某个数,显然图中没有0一定不比有0劣(把所有0改成同一个数一定不劣)。然后把单次计算的复杂度从\(O(n^2)\)变成\(O(1)\):更新有变化位置的值就行了。瞎调调参数......
  • atcoder beginner 346 题解
      看到别人的视频讲解 AtCoderBeginnerContest346A至G題讲解bydreamoon C如果用sort写,那么再从小到大遍历也需要写几行#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<cstdbool>#include<string>#include<......
  • AtCoder Beginner Contest 346
    AtCoderBeginnerContest346比赛链接A-AdjacentProduct思路:b[i]=a[i]*a[i+1]Code#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#defineall(x)x.begin()+1,x.end()voidsolve(){ intn; cin>>n; std::vector<in......
  • Atcoder
    D-食塩水\[\frac{\sum{w_ip_i}}{\sum{w_i}}\gex\\\sum{w_i(p_i-x)}\ge0\\\]fromcollectionsimport*fromitertoolsimport*fromfunctoolsimport*defLI():returnlist(map(int,input().split()))defI():returnint(input())de......
  • Atcoder ABC245H Product Modulo 2
    发现这个\(m\)很大,且这个式子是\(\times\)。一个想法是拆成\(m=\prod{p_i}^{e_i}(p_i\in\mathbb{P})\)然后对于\(M=p_i^{e_i}\)依次考虑\(b_i=a_i\bmodM\)和\(N=n\bmodM\)。根据\(\text{CRT}\),对于任意一个\(M\)得到的不同的\(b_i\)对于最后的\(a_i......
  • UNIQUE VISION Programming Contest 2024 Spring(AtCoder Beginner Contest 346)
    C我们用\(1\simK\)的和减去出现在\(1\simK\)中的数的和。intn,k,a[N],res;map<int,int>vis;signedmain(){ cin>>n>>k; _for(i,1,n)cin>>a[i]; res=k*(1+k)/2; _for(i,1,n)if(a[i]>=1&&a[i]<=......
  • Atcoder ABC 346 全题解
    闲话上一篇全题解反向不错,如果大家支持我就会继续更。我ABC也打了,ARC也打了,没打好,疯狂掉大分……包括本场比赛也是整整补了EFG三道题,以及ARC死磕D结果使赛后五分钟AC又有素材了……A懒得讲B由于我被B题坑了,所以在此纪念。最简单的方法就是把字符串复制......