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

AtCoder Beginner Contest 367

时间:2024-08-19 12:48:12浏览次数:5  
标签:AtCoder r1 Beginner int cin r2 l2 l1 367

题目链接:AtCoder Beginner Contest 367

总结:发挥很一般,A一直wa。开场有点事,导致D也没debug出来。

A. Shout Everyday

tag:模拟
Solution:注意\(B > C\)与\(B < C\)的不同情况即可。

void solve(){
    int a, b, c;
    cin >> a >> b >> c;
    if (c > b){
        if (a >= c || a < b){
            cout << "Yes\n";
        }
        else{
            cout << "No\n";
        }
    }
    else{
        if (a >= c && a < b){
            cout << "Yes\n";
        }
        else{
            cout << "No\n";
        }
    }
}

B. Shout Everyday

tag:模拟
Solution:从后往前去掉对于的\(0\),然后看是否需要去掉.

void solve(){
    string s;
    cin >> s;
    int i;
    for (i = s.size() - 1; i > 0; i --){
        if (s[i] != '0')
            break;
    }
    if (s[i] == '.'){
        for (int j = 0; j < i; j ++)
            cout << s[j];
    }
    else{
        for (int j = 0; j <= i; j ++)
            cout << s[j];
    }
}

C. Enumerate Sequences

tag:dfs
Solution:根据题意模拟即可

void solve(){
    int n, k;
    cin >> n >> k;
    vector<int> a(n + 10);
    for (int i = 1; i <= n; i ++)
        cin >> a[i];
    
    function<void(int, string)> dfs = [&](int s, string ans) {
        if (s == n){
            int sum = 0;
            for (int i = 0; i < n; i ++)
                sum += ans[i] - '0';
            if (sum % k == 0){
                for (int i = 0; i < n; i ++){
                    cout << ans[i] << " ";
                }
                cout << endl;
            }
        }
        else{
            for (int i = 1; i <= a[s + 1]; i ++){
                dfs(s + 1, ans + char(i + '0'));
            }
        }
    };
    dfs(0, "");
}

D. Pedometer

tag:前缀和哈希 + 环形
Solution:很典的前缀和哈希。但是需要处理一个环形,同时注意值的计算,\(i -> i + 1\)的值为\(a_i\)。

  • 第一轮循环处理:s < t的情况
  • 第二轮循环处理:s > t的情况(注意这里不能重复计算s < t的方案数)
    Competing:没注意到从\(i -> i + 1\)是\(a_i\),而不是\(a_i + a_{i + 1}\)。
void solve(){
    cin >> n >> m;
    vector<int> a(n + 10);
    for (int i = 1; i <= n; i ++)
        cin >> a[i];
        
    int ans = 0;
    map<int, int> mp;
    int t = 0;
    for (int i = 1; i <= n; i ++){  // 第一次处理s < t的情况
        // 以i为结尾
        ans += mp[t];
        mp[t] ++;
        t = (t + a[i]) % m;
    }
    int res = 0;
    for (int i = 1; i < n; i ++){ // 注意这里小于n
        mp[res % m] --;
        ans += mp[t % m];
        res = (res + a[i]) % m;
        t = (t + a[i]) % m;  // 这里mp[t]不需要再加了,否则会重复计算s < t的方案数
    }

    cout << ans;
}

E. Permute K times

tag:倍增
Description:给定两个长度为\(n\)的数组\(x, a\),需要执行\(k\)次操作,每次操作:

  • 先令所有\(b_i = a_{x_i}\), 然后令\(a = b\)。
  • 求最后的\(a\)数组。
  • \(1 <= n <= 2 * 10^5, 0 <= k <= 10^{18}\)。
    Solution:注意到\(x\)数组是不变的,意味着第\(i\)个位置的变化是固定的:$i -> x_i -> x_{x_i}。
  • 我们需要知道第\(i\)个数变换\(k\)次之后所在的位置,但是\(k\)的范围很大,考虑预处理。
  • 使用倍增预处理:\(f[i][j]\)表示第\(i\)个位置的数,执行\(2^j\)次操作后所在的位置。
  • \(f[i][j] = f[f[i][j - 1]][j - 1]\)
int f[N][65];
void solve(){
    cin >> n >> k;
    vector<int> x(n + 1), a(n + 1);
    for (int i = 1; i <= n; i ++)
        cin >> x[i];
    for (int i = 1; i <= n; i ++)
        cin >> a[i];

    for (int j = 0; j <= 64; j ++){
        for (int i = 1; i <= n; i ++){
            if (!j){  // 第i个元素执行2^j操作后的位置
                f[i][j] = x[i];
            }
            else{
                f[i][j] = f[f[i][j - 1]][j - 1]; 
            }
        }
    }

    vector<int> t;
    for (int i = 0; i < 64; i ++){
        if ((k >> i) & 1){
            t.push_back(i);
        }
    }
    for (int i = 1; i <= n; i ++){
        int tt = i;
        for (int j : t){
            tt = f[tt][j];
        }
        cout << a[tt] << " ";
    }
}

F. Rearrange Query

tag:哈希
Description:给定两个长度为\(n\)的数组\(a, b\),执行\(Q\)次查询,每次查询给定:

  • \(l1, r1, l2, r2\),询问\(a[l1, r1], b[l2, r2]\)区间内的数,重新排序后是否能够匹配。
  • \(1 <= n, Q <= 2 * 10^5, 1 <= a_i, b_i <= n\)。
    Solution:我们需要统计区间内每个数出现的次数,但是每次查询暴力查询显然会超时。
  • 类似字符串哈希,我们将每个数哈希为一个\(N\)位\(M\)进制的数。
void solve(){
    cin >> n >> k;
    vector<ull> p(n + 10);
    p[0] = 1;
    for (int i = 1; i <= n; i ++)
        p[i] = p[i - 1] * 1331;
    
    vector<ull> ha(n + 10), hb(n + 10);

    for (int i = 1; i <= n; i ++){
        int x;
        cin >> x;
        ha[i] = ha[i - 1] + p[x];
    }
    for (int i = 1; i <= n; i ++){
        int x;
        cin >> x;
        hb[i] = hb[i - 1] + p[x];
    }

    function<bool(int, int, int, int)> query = [&](int l1, int r1, int l2, int r2) {
        ull a = ha[r1] - ha[l1 - 1];
        ull b = hb[r2] - hb[l2 - 1];
        return a == b;
    };

    while (k --){
        int l1, r1, l2, r2;
        cin >> l1 >> r1 >> l2 >> r2;
        if (query(l1, r1, l2, r2)){
            cout << "Yes\n";
        }
        else{
            cout << "No\n";
        }
    }
}

标签:AtCoder,r1,Beginner,int,cin,r2,l2,l1,367
From: https://www.cnblogs.com/Sakura17/p/18367101

相关文章

  • 题解:AT_abc367_c [ABC367C] Enumerate Sequences
    大致题意让你按照字典序输出一些长\(n\)的序列,序列中的数字有范围,且序列和需要为\(k\)。分析直接深搜。搜索的时候对从第一个元素开始,每个元素从小到大枚举所有可能的值,这样就保证答案按照字典序升序排列。用一个vector存储序列,到达边界之后计算一遍和,判断是否满足条件,然......
  • ABC 367D Pedometer
    题意给定N个人成的环,第i个人到第i+1个人之前的距离为a[i](第N个人到第1个人的距离为a[n]),每个人只能顺时针走动。求问有多少点对(s,t)使得第s个人走到第t个人的距离是M的倍数。思路对于这种环状问题,我们最开始的思路就是开个双倍数组把环破坏成链转换成线性问题。接下来就是我们......
  • ABC 367 G 题解
    ABC367G神奇题目场上想到了引入多元生成函数之后就嗝屁了。定义两个多项式的运算\(A(z)*B(z)=\sum_{i}\sum_{j}z^{i\oplusj}a_ib_j\),也就是异或卷积。定义两个二元生成函数\(A(x,y)*B(x,y)=\sum_{i,p}\sum_{j,q}x^{i\oplusj}y^{p+q}a_{i,p}b_{j,q}\)我们仍然选用\(\prod......
  • [LeetCode] 1367. Linked List in Binary Tree 二叉树中的链表
    Givenabinarytree root anda linkedlistwith head asthefirstnode.ReturnTrueifalltheelementsinthelinkedliststartingfromthe head correspondtosome downwardpath connectedinthebinarytree otherwisereturnFalse.Inthiscontext......
  • 题解:AT_abc367_d [ABC367D] Pedometer
    首先肯定要单层循环枚举元素,然后想方法求出一个元素的所有答案。一开始我写了一个二分找\(m\)倍数的方法,发现\(m\)小的时候还不如暴力。于是联想到之前做过的一道题,可以借助于取模的前缀和数组。对于当前元素\(i\),如果一个元素之前的前缀和与\(i\)之前的前缀和对\(m\)......
  • Atcoder [ABC367F] Rearrange Query 题解
    简要题意给定两个长度为\(N\)的序列\(A\)和\(B\)。有\(Q\)个查询,每个查询给定\(l,r,L,R\),其中\(l\leqr,L\leqR\),要求判断\(A\)的第\(l\)项到第\(r\)项构成的集合与\(B\)的第\(L\)项到第\(R\)项构成的集合是否相等。题解显然两个相等的集合所有元素......
  • Atcoder [ABC367C] Enumerate Sequences 题解
    简要题意给定\(n,k\)和\(R_i\),你需要输出所有满足下列条件的整数序列:长度为\(n\)。第\(i\)个元素的范围为\([1,R_i]\)。一个序列的所有元素的总和为\(k\)的倍数。输出请按照按照从左至右按位从小到大的顺序输出。题解注意到数据范围很小,我们可以直接爆搜,这里用......
  • 题解:AT_abc367_e [ABC367E] Permute K times
    题意给你一个长度为\(N\)的序列\(X\),其中每个元素都介于\(1\)和\(N\)之间(含),以及一个长度为\(N\)的序列\(A\)。打印在\(A\)上执行以下操作\(K\)次的结果。将\(A_i\)替换为\(A_{X_i}\)。每个操作同时进行。思路元素\(i\)经过\(k\)次变化后的值就是元素......
  • AtCoder Beginner Contest 367 题解(E~G)
    E转换关系看作有向边,\(n\)点\(n\)边构成基环树森林,基环树森林k后继唯一,记f[i][j]为点\(i\)的\(2^j\)级祖先,随便倍增。F一眼哈希,不知道有没有不哈希的做法。在这里我们不关心元素的顺序,只关心元素是否出现以及出现几次,考虑一个\(n\)位\(n+1\)进制数,\(a_i\)出现一......
  • Atcoder Beginner Contest 367
    A.ShoutEveryday\(\text{Diff}43\)给你\(24\)小时制下的\(A,B,C\)三个时刻,问\(A\)是否在\([B,C]\)范围内考虑到先将\(B,C\)加上一个\(24\),假如\(C\)比\(B\)小,将\(C\)再加上一个\(24\),这样可以保证严格的\(A\ltB,C\),此时直接判断是否存在一个\(k\),使得......