厨方网

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 157|回复: 7

Codeforces Round #828 (Div. 3) A

[复制链接]

2

主题

3

帖子

7

积分

新手上路

Rank: 1

积分
7
发表于 2022-11-30 13:19:43 | 显示全部楼层 |阅读模式
首先是后悔E2在那里用全局变量导致一直wa28,也不知道为什么改vector就过了,然后是F思路对了没写下去又或者是思路没完全对。。。这场还是能体现代码功底的吧,反正我是被折磨了,菜死了。
进入正题:
<hr/>A. Number Replacement 模拟

题意:
给定一个数组和一个字符串,每次选择数组中的一个数和一个字符,把字符串中所有的该字符都替换成该字符,求能否将数组变成该字符串。
分析:
对于无解的情况是在s中相同的位置但是在原数组中不同,用map存上一个a的位置判断在s中是否相同即可。
时间复杂度:O(n)
代码:
void solve()
{
    cin >> n;
    for(int i = 1 ; i <= n ; i ++ ) cin >> a;
    cin >> s;
    s = "?" + s;
    map<int, int> mp;
    for(int i = 1; i <= n ; i ++ ) {
        if(!mp[a]) mp[a] = i;
        else {
            if(s != s[mp[a]]) NO;
            mp[a] = i;
        }
    }
    YES;
}
B. Even-Odd Increments 模拟

题意:
给定一个数组,每次一个操作:让偶数元素+v或者让奇数元素+v,求每次操作后的数组总和。
分析:
统计出偶数和奇数的数量,然后在累加的时候维护其奇偶数量的变化。
时间复杂度:O(n + m)
代码:
void solve()
{
    cin >> n >> m;
    int sum = 0;
    int aa = 0, bb = 0;
    for(int i = 1 ; i <= n ; i ++ ) {
        cin >> a , sum += a;
        if(a & 1) bb ++ ;
    }
    aa = n - bb;
   
    while(m -- ) {
        int op, v;
        cin >> op >> v;
        if(op == 0) {
            sum += aa * v;
            if(v & 1) bb += aa, aa = 0;
        }
        else {
            sum += bb * v;
            if(v & 1) aa += bb, bb = 0;
        }
        cout << sum << endl;
    }
}
C. Traffic Light 模拟

题意:
给定红绿灯的循环节,以及你初始看到的灯,求下一个绿灯等待的最长时间。
分析:
把循环节复制一遍,在2n的序列上从后往前判断最大值即可。
代码:
void solve()
{
    char c;
    cin >> n >> c;
    cin >> s;
    s = "?" + s + s;
    int mx = 0, last = 0;
    for(int i = 2 * n; i >= 1 ; i -- ) {
        if(s == 'g') last = i;
        if(s == c) mx = max(mx, last - i);
    }
    cout << mx << endl;
}
D. Divisibility by 2^n 贪心

题意:
给定一个数组,要求进行若干次操作,使得a乘i上的数,每个数都能最多被乘一次,求最少的操作次数使得数组的乘积能够被2^n整除。
分析:
在数组中找出2的因子个数,如果满足了n个ans就是0,否则需要通过操作来补足。操作出1-n所有数中2因子的数量,优先操作2因子数量最大的数。
时间复杂度:O(nlogn)
代码:
void solve()
{
    cin >> n;
    int res = 0;
    vector<int> v;
    for(int i = 1; i <= n ; i ++ ) {
        cin >> a;
        int t = a;
        while(t % 2 == 0) t /= 2, res ++ ;
        t = i;
        int s = 0;
        while(t % 2 == 0) t /= 2, s ++ ;
        if(s) v.push_back(s);
    }
   
    if(res >= n) cout << 0 << endl;
    else {
        sort(v.begin(), v.end());
        reverse(v.begin(), v.end());
        int l = 0;
        int V = n - res;
        // cout << V << endl;
        int ans = 0;
        while(l < v.size() && V) {
            if(v[l] <= V) ans ++ , V -= v[l];
            l ++  ;
        }
        if(V) cout << -1 << endl;
        else cout << ans << endl;
    }
}
E. Divisible Numbers 暴力枚举质因子

题意:
给定4个数,abcd,要求找到一组<x, y>使得x * y能够被 a * b整除。
分析:
abcd的范围是1e9,但是我们发现1e9的因子数量其实并不多。
我们考虑枚举a*b的所有因子,1e18的所有因子的数量大概是100000个,别问,这个数量的增加和质数的种类有很大关系,但是1e18的质数的种类不会超过20个,因此记住这个重要的结论就可以qwq。
dfs枚举出a * b的所有因子,然后开始枚举。x为第一个因子,y为第二个因子a*b/x,然后O1找到第一个大于等于a+1和b+1的位置,判断是否均小于c和d即可。
时间复杂度:O(100000)
代码:因为我的码子蜜汁离谱,还开的全局变量,贴了胶老师码子大家欣赏一下。
void init() {
    for (int i = 2; i < N; i++) {
        if (!st) primes[cnt++] = i;
        for (int j = 0; primes[j] * i < N; j++) {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

void dfs(int now, int prod) { // dfs爆搜因子
    if (prod > c) return;
    if (now == fs.size()) {
        if (r / prod <= d) ds.push_back(prod);
        return;
    }
    int p = fs[now].first, c = fs[now].second;
    for (int i = 0; i <= c; i++) {
        dfs(now + 1, prod);
        prod *= p;
    }
}

void solve() {
    fs.clear(), ds.clear();
    cin >> a >> b >> c >> d;
    int bb = a;
    map<int, int> mp;
    for (int i = 0; primes <= bb / primes; i++) {
        int p = primes;
        if (bb % p == 0) {
            while (bb % p == 0) mp[p]++, bb /= p;
        }
    }
    if (bb > 1) mp[bb]++;
    bb = b;
    for (int i = 0; primes <= bb / primes; i++) {
        int p = primes;
        if (bb % p == 0) {
            while (bb % p == 0) mp[p]++, bb /= p;
        }
    }
    if (bb > 1) mp[bb]++;
    for (auto [x, y] : mp) fs.push_back({x, y});
    r = a * b;
    dfs(0, 1);
    int p = -1, q = -1;
    if (ds.size()) {
        for (auto x : ds) {
            int y = r / x;
            x = (a / x + 1) * x;
            y = (b / y + 1) * y;
            if (x <= c && y <= d) {
                 p = x, q = y;
                 return ;
            }
        }
    }
    cout << p << ' ' << q << '\n';
}
F. MEX vs MED 统计问题

题意:
给定一个由0-n-1组成的数组,统计出这样的区间[l, r]当且仅当区间的中位数 < mex[l, r] , mex表示区间内第一个不存在的自然数。
分析:
赛时的思路有点正确的,但不是完全正确,感谢cup_pyy帮我实现了我赛时未完成的思路,大家可以看他的:
链接:
我们发现mex的特性是想要mex变大,必须在区间内包含从0开始的所有数,根据这个特性,我们可以通过限定mex来统计出在某一个mex值的情况下,有多少满足的区间。
假设我们目前的区间[L, R]的mex函数是p,那么这个在保证中位数<p的条件下,需要保证序列长度max_len <= (p + 1) * 2。因此我们每次从一个p出发开始拓展到p + 1并更新区间,在max_len的限制下去统计合法区间的数量。
每次找到下一个改变mex的位置,也就是pos[p + 1],然后看看这个位置在左边还是在右边,统计出数量即可。
回复

使用道具 举报

0

主题

2

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2022-11-30 13:20:03 | 显示全部楼层
胶ls[看看你][看看你]
回复

使用道具 举报

1

主题

2

帖子

3

积分

新手上路

Rank: 1

积分
3
发表于 2022-11-30 13:20:45 | 显示全部楼层
E为什么x,y一定是a*b因子的倍数呢?
回复

使用道具 举报

0

主题

2

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2022-11-30 13:21:32 | 显示全部楼层
因为xy一定分摊了ab的因子
回复

使用道具 举报

0

主题

1

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2022-11-30 13:22:24 | 显示全部楼层
太强啦!!!
回复

使用道具 举报

0

主题

1

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2022-11-30 13:23:19 | 显示全部楼层
E题应该是使得x * y能够被 a * b整除吧。
回复

使用道具 举报

0

主题

1

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2022-11-30 13:23:59 | 显示全部楼层
说反了qwq
回复

使用道具 举报

0

主题

2

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2022-11-30 13:24:38 | 显示全部楼层
E题 找到第一个大于等于a+1和b+1的位置 这里用8 9 15 18这组数据是不是就hack掉了啊?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|厨方网

GMT+8, 2025-4-18 07:52 , Processed in 0.099560 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表