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

Atcoder Beginner Contest 367

时间:2024-11-18 20:48:19浏览次数:3  
标签:pre Atcoder 前缀 Beginner int cin long 哈希 367

老规矩此处略过前三题,不过B值得关注一下。

D题 Pedometer

思路肥肠煎蛋,只需要搞一个前缀额然后看前面的前缀和是否有跟当前的前缀和同余的情况(%M)

暴力求解这步是O(n^2)的,因此需要优化。这里就用到了一个技巧——哈希表消除分支。

所谓的哈希表消除分支其实就是mp[pre_s]存一下看前面有多少个和为pre_s前缀和。

如果当前的前缀和是S % M,那么只需要去前面找mp[S % M]。

对于一个环状的情况,可以将数组复制两份——破环成链!!!

#include<iostream>
#include<cstring>
#define int long long

using namespace std;
const static int N = 1000010;
int a[N], b[N];

signed main(){
    memset(b, 0, sizeof b);
    int n, k;
    cin >> n >> k;
    b[0] = 1;
    int s = 0;
    int ans = 0;
    for(int i = 0; i < n; i++)
        cin >> a[i];
    for(int i = 0; i < n - 1; i++){    
        s += a[i];
        ans += b[s % k];
        b[s % k]++;
    }
    
    int s1 = 0;
    for(int i = n - 1; i > 0; i--){
        b[s % k]--;
        s -= a[i - 1];
        s1 += a[i];
        ans += b[(k - (s1 % k)) % k];
    }
    cout << ans << endl;
    return 0;
}

E题 Permute K times

这个题非常经典,首先注意到数据范围——操作次数K的范围在1e18,显然我们不能枚举每次操作。

这个时候就需要用到倍增。st[i][j]表示从下标i开始,进行2^j次操作后的下标。那么对于1e18次操作,我们只需要大约60次枚举就行。

因此,对于每一个下标,直接进行枚举就完美解决问题了。

#include<iostream>
#define int long long

using namespace std;

const static int N = 200010, M = 63;
int n, k;
int a[N], X[N], st[N][M];

signed main(){
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> k;
    for(int i = 1; i <= n; i++)cin >> X[i];
    for(int i = 1; i <= n; i++)cin >> a[i], st[i][0] = X[i];
    
    //枚举步数
    for(int j = 1; j < M; j++){
        for(int i = 1; i <= n; i++){
            st[i][j] = st[st[i][j - 1]][j - 1];
        }
    }

    for(int i = 1; i <= n; i++){
        int x = i, t = k;
        for(int j = M - 1; j >= 0; j--){
            if(t >= (1ll << j)){
                t -= (1ll << j);
                //跳2^j步
                x = st[x][j];
            }
        }
        cout << a[x] << ' ';
    }
    return 0;
}

F题 Rearrange Query

问题很简单,对于每次询问,就是回答A[L,R]和B[L,R]之间的元素是否能够一一对应,即我们要快速维护每个数频率。这个时候就考验你对已学知识的掌握了。字符串哈希的思想。

我们只需要找到一个大质数(类似大数取模哈希),然后分别为每一个值分配一个哈希值。因为数组元素的范围为1\leqslant Ai,Bi\leqslant N,因此我们可以直接枚举1 ~ N,为每一个数分配一个权值,类似十进制给每个数位分配权值。

然后查询就直接用前缀和比较两个子数组的映射值是否相同即可。

#include<bits/stdc++.h>

using namespace std;

typedef unsigned long long ull;
const static ull M = 9982443537;

void solve() {

    int n, q, v;
    cin >> n >> q;
    vector<ull> P(n + 1), a(n + 1), pre(n + 1);
    P[0] = 1;
    for(int i = 1; i <= n; i++) {
        P[i] = P[i - 1] * M;
    }
    for(int i = 1; i <= n; i++) {
        cin >> v;
        a[i] = a[i - 1] + P[v];
    }
    
    for(int i = 1; i <= n; i++) {
        cin >> v;
        pre[i] = pre[i - 1] + P[v];
    }

    while(q--) {
        int x1, x2, y1, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        //直接比较两个子数组的映射值
        if(a[y1] - a[x1 - 1] == pre[y2] - pre[x2 - 1]) {
            cout<< "Yes" << endl;
        } else {
            cout<< "No" << endl;
        }
    }
    return;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    while(t--) {
        solve();
    }
    return 0;
}

有同学会问这个大质数怎么来的,wa两发就出来了[doge]

本文到此结束。

标签:pre,Atcoder,前缀,Beginner,int,cin,long,哈希,367
From: https://blog.csdn.net/q13377539482/article/details/143730017

相关文章

  • AtCoder Beginner Contest 380 (A~E)题解
    A-123233遍历字符串统计出现次数即可。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintN=1e6+10;intn,m,k;inta[N];signedmain(){ strings; cin>>s; map<char,int>mp; for(autot:s){ mp[t]++; } if(......
  • [题解]AtCoder Beginner Contest 380(ABC380) A~F
    A-123233照题意统计即可。点击查看代码#include<bits/stdc++.h>usingnamespacestd;strings;map<char,int>ma;signedmain(){ cin>>s; for(chari:s)ma[i]++; if(ma['1']==1&&ma['2']==2&&ma['3']==3)co......
  • 【未完结】 AtCoder Beginner Contest 380 题解
    AtCoderBeginnerContest380Rated:\(770\)A-123233简单模拟B-HurdleParsing字符串模拟C-MoveSegment找到第\(k\)个块的下标,模拟。D-StrangeMirroringE-1DBucketToolF-ExchangeGameG-AnotherShuffleWindow......
  • 【AtCoder】Beginner Contest 378-E.Mod Sigma Problem
    题目链接ProblemStatementYouaregivenasequenceA=(A1......
  • 【AtCoder】Beginner Contest 378-F.Add One Edge 2
    [题目链接](F-AddOneEdge2(atcoder.jp))ProblemStatementYouaregivenatreewithNNNvertices.Thei......
  • AtCoder Beginner Contest 380 A - E
    link赛时是ABC,D一眼要找规律,跳了,E题思路想了接近半个小时,然后发现假了,最后没调出来,问一下dalao发现其实很简单维护。。。基础线段树没切掉,哎呦不过发现比赛打多了,理解速度和手速都有些提高,幸好前三题秒掉了,要不然rating又会是一坨A-123233B-HurdleParsingC-M......
  • AtCoder Beginner Contest 380
    省流版A.计数判断即可B.计数统计即可C.模拟即可D.注意到字符串是左右大小写镜像,从长度大往小依次考虑实际所处的位置,维护镜像次数集合E.并查集维护连通性,并尝试与左右俩格子合并即可F.博弈\(dp\),状态数只有\(5e5\),直接记忆化搜索即可G.枚举打乱起始位置,全排列分......
  • Atcoder 11.17
    这是11.17号的题单4.第四题是字符串的问题,只需要找到规律即可,对于每个查询k[i],首先计算a和aa:a是(k[i]-1)//ls,即k[i]-1除以字符串长度ls的商。这相当于确定k[i]在重复字符串中属于第几个完整的字符串块。aa是bin(a).count("1")%2,即a的二进制表示中"1"......
  • AtCoder Beginner Contest 380
    A-123233题意给个\(6\)位数,判断是否是\(1\)个\(1\),\(2\)个\(2\),\(3\)个\(3\)。思路模拟。代码点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongtypedefpair<int,int>pii;constintmxn=1e6+5;voidsolve(){ s......
  • AtCoder Grand Contests 杂做
    感觉AGC003及以前的题做了大部分,所以从AGC004开始,选一些我觉得合适的题做。AGC004E-*3200一直在往静态的几何(或者代数)限制想,结果没想到可以动态规划。为了更加直观可以看作出口在移动,然后到过的点加分,某些出界的点就被ban掉了。我们可以直接考虑定义\(f_{l,r,u,d}\)......