Codeforces Round #748 (Div. 3) -> VP

A (简单模拟)-Elections

题意:

给出三个整数,每次对这个整数加1,问对于每一个整数,最少需要几次操作可以使得,他变成三个数中唯一的最大值.

思路:

对于不等于 max 的元素,最少操作次数为 max - x + 1.

对于等于max 的元素,如果有多个数字等于 max 的话,那么最少操作次数就是1,否则是0. 

参考代码:

void solve() {
    std::vector<int> a(3);
    std::cin >> a[0] >> a[1] >> a[2];
    int max = *max_element(a.begin(),a.end());
    bool f1 = false, f2 = false;
    for (int i = 0; i < 3; i++) {
        if (a[i] == max) {
            if (!f1) {
                f1 = true;
            } else {
                f2 = true;
                break;
            }
        }
    }

    for (int i = 0; i < 3; i++) {
        if (a[i] == max) {
            a[i] = f2;
        } else {
            a[i] = max - a[i] + 1; 
        }
    }
    for (int i = 0; i < 3; i++) {
        std::cout << a[i] << " \n"[i == 2];
    }
}

B (思维.BFS) -Make it Divisible by 25

题意:

给你一个数字,每一次可以删去任意一位数字,问最少需要多少次操作,使得这个数字是 25 的倍数?

思路:

因为 25 ∗ 4 = 100

所以,对于百位即以上的位数,无论我们取什么都可以整除

我们只需关注个位和十位

因此,每次删除要么删除个位上的数,要么删除十位上的数,这样一来枚举的情况就大大减少了

我们 bfs.

参考代码:

#include <bits/stdc++.h>
using pll = std::pair<ll, ll>;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    std::function<int(ll)> bfs = [&](ll num) {
        std::queue<pll> que;
        que.push({num, 0});

        std::map<ll, bool> mp;
        while (!que.empty()) {
            pll p = que.front();

            que.pop();
            if (p.first < 25) {
                continue;
            }

            if (p.first % 25 == 0) {
                return p.second;
            }

            pll pp = {p.first / 10, p.second + 1};
            pll ppp = {p.first / 100 * 10 + p.first % 10, p.second + 1};


            mp[pp.first] = 1;
            que.push(pp);


            mp[ppp.first] = 1;
            que.push(ppp);
        }
    };

    int T;
    std::cin >> T;
    while (T--) {
        ll num;
        std::cin >> num;
        std::cout << bfs(num) << "\n";
    }
    return 0;
}

C (贪心.模拟.前缀和.二分) -Save More Mice

思路:

贪心,让距离洞口近的老鼠先出发躲到洞中,如果猫的 pos < 老鼠的 pos,那么这一只老鼠可以进入洞中躲起来,否则,将被猫抓到.

参考代码:

    while (t--) {
        int n, k;
        std::cin >> n >> k;
        std::vector<int> a(k);
        for (int i = 0; i < k; i++) {
            std::cin >> a[i];
        }
        
        int pos = 0, ans = 0;
        std::sort(a.begin(), a.end(), std::greater<int>());

        for (int i = 0; i < k; i++) {
            if (a[i] > pos) {
                ans++;
                pos += n - a[i];
            } else {
                break;
            }
        }
        std::cout << ans << "\n";
    }
    while (t--) {
        int n, k;
        std::cin >> n >> k;
        std::vector<int> a(k + 1);
        for (int i = 1; i <= k; i++) {
            std::cin >> a[i];
        }
        std::sort(a.begin() + 1, a.end(), std::greater<int>());
        std::vector<ll> sum(k + 1);
        for (int i = 1; i <= k; i++) {
            sum[i] = sum[i-1] + (n - a[i]);
        }
        std::cout << std::lower_bound(sum.begin() + 1,sum.end(),n)-sum.begin() - 1 << '\n';
    }

D1 (思维.数论)-All are Same 

思路:

两个数 a,b,对这两个数执行操作

a减去 x 个k,b 减去 y 个k.

如此a - x*k = b − y*k.

那么 a %k == b %k.

a,b对 k 取余的余数一定要相同

那么(a − b) mod k = 0

k 一定为 abs(a - b)中的因数!

我们随意找两个数 a,b,枚举 abs(a - b)的因数一一验证即可

参考代码:

#include <bits/stdc++.h>

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T;
    std::cin >> T;
    while (T--) {
        int n;
        std::cin >> n;
        std::vector<int> a(n);
        for (int i = 0; i < n; i++) {
            std::cin >> a[i];
        }

        std::function<bool(int)> check = [&](int num) {
            for (int i = 1; i < n; i++) {
                if ((a[i] % num + num) % num != (a[i - 1] % num + num) % num)
                    return false;
            }
            return true;
        };

        std::sort(a.begin(), a.end());
        int big = a[n - 1] - a[0];
        int ans = -1;
        for (int i = 1; i * i <= big; i++) {
            if (big % i == 0) {
                if (i > ans && check(i)) {
                    ans = i;
                }
                if (big / i > ans && check(big / i)) {
                    ans = big / i;
                }
            }
        }

        std::cout << ans << "\n";
    }
    return 0;
}

D2 (思维.数论)- Half of Same

基本策略和 D1并没有什么不同

只是这里要求如果有至少一半的数字他们关于k同余即可

如此,我们可以枚举所有的数字对,

按照 D1 的策略找到所有的 k,能满足至少有一半的元素同余.

参考代码:

#include <bits/stdc++.h>

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T;
    std::cin >> T;
    while (T--) {

        int n;
        std::cin >> n;
        std::vector<int> a(n);
        std::function<bool(int)> check = [&](int num)
        {
            std::map<int, int> mp;
            for (int i = 0; i < n; i++) {
                mp[(a[i] % num + num) % num]++;
            }
            for (auto p : mp) {
                if (p.second >= n / 2) {
                    return true;
                }
            }
            return false;
        };
        std::function<int(int)> solve = [&](int num)
        {
            int ans = 0;
            for (int i = 1; i * i <= num; i++) {
                if (num % i == 0) {
                    if (i > ans && check(i)) {
                        ans = i;
                    }    
                    if (num / i > ans && check(num / i)) {
                        ans = num / i;
                    }
                }
            }
            return ans;
        };
        for (int i = 0; i < n; i++) {
            std::cin >> a[i];
        }
            
        std::sort(a.begin(), a.end());
        std::map<int, int> mp;
        for (int i = 0; i < n; i++) {
            mp[a[i]]++;
        }
            
        int ans = 0;
        for (auto p : mp) {
            if (p.second >= n / 2) {
                ans = -1;
                break;
            }
        }
            
        if (ans == -1) {
            std::cout << ans << "\n";
            continue;
        }

        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                ans = std::max(ans, solve(a[j] - a[i]));
            }
        }
                
        std::cout << ans << "\n";
    }
    return 0;
}

E.(BFS) - Gardener and Tree

一个点可删除,当且仅当他的度数 ≤1

我们记录下所有的度数,从所有度数 ≤1 的点开始 bfs 即可

保证 bfs 的层数 ≤ k

答案便是 n − 所有走过的点数.

参考代码:

#include <bits/stdc++.h>

const int maxn = 4e5 + 100;
std::vector<int> G[maxn];
bool de[maxn];
int du[maxn];
int n, k;
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T;
    std::cin >> T;
    while (T--) {
        std::cin >> n >> k;
        for (int i = 1; i <= n; i++) {
            G[i].clear(), du[i] = de[i] = 0;
        }
        for (int i = 1, u, v; i < n; i++) {
            std::cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
            du[u]++;
            du[v]++;
        }
        std::queue<std::pair<int, int>> que;
        for (int i = 1; i <= n; i++) {
            if (du[i] <= 1) {
                que.push({i, 1});
            }
        }

        while (!que.empty()) {
            std::pair<int, int> p = que.front();
            que.pop();
            if (de[p.first]) {
                continue;
            }
            de[p.first] = 1;
            if (p.second == k) {
                continue;
            }
            for (int v : G[p.first]) {
                du[v]--;
                if (du[v] <= 1 && !de[v])
                    que.push({v, p.second + 1});
            }
        }
        int ans = n;
        for (int i = 1; i <= n; i++) {
            if (de[i]) {
                --ans;
            }                
        }
        std::cout << ans << "\n";
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值