当前位置:首页 > 技术 > 正文内容

Codeforces Round 636 (Div. 3) 算法思路与代码实现

访客 技术 2026年10月27日 1

A. Candies

题目要求寻找一个正整数 $x$,使得对于某个 $k > 1$,满足等比数列之和 $x + 2x + 4x + \dots + 2^{k-1}x = n$。根据等比数列求和公式,该式可简化为 $x(2^k - 1) = n$。因此,我们只需要枚举 $k$(从 2 开始),检查 $n$ 是否能被 $2^k - 1$ 整除即可。

#include <iostream>

using namespace std;

void solve() {
    long long n;
    cin >> n;
    for (int k = 2; k < 31; ++k) {
        long long denominator = (1LL << k) - 1;
        if (n % denominator == 0) {
            cout << n / denominator << endl;
            break;
        }
    }
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

B. Balanced Array

构造一个长度为 $n$ 的数组,要求前 $n/2$ 个元素为偶数,后 $n/2$ 个元素为奇数,且两部分和相等。 由于偶数之和必为偶数,若 $n/2$ 为奇数,则后半部分($n/2$ 个奇数)的和必为奇数,两者不可能相等。因此只有当 $n/2$ 为偶数时才存在解。构造时,前 $n/2$ 个数取 $2, 4, 6, \dots$,后 $n/2$ 个数的前 $n/2-1$ 个取 $1, 3, 5, \dots$,最后一个数通过差值补齐。

#include <iostream>
#include <vector>

using namespace std;

void solve() {
    int n;
    cin >> n;
    int m = n / 2;
    if (m % 2 != 0) {
        cout << "NO" << endl;
        return;
    }
    cout << "YES" << endl;
    vector<long long> res;
    long long even_sum = 0;
    for (int i = 1; i <= m; ++i) {
        res.push_back(i * 2);
        even_sum += i * 2;
    }
    long long odd_sum = 0;
    for (int i = 1; i < m; ++i) {
        res.push_back(i * 2 - 1);
        odd_sum += (i * 2 - 1);
    }
    res.push_back(even_sum - odd_sum);
    for (int i = 0; i < n; ++i) {
        cout << res[i] << (i == n - 1 ? "" : " ");
    }
    cout << endl;
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

C. Alternating Subsequence

给定一个序列,求其最长的正负交替子序列的最大和。 贪心策略:由于要保证长度最长,我们必须在每一段连续的正数或连续的负数中各取一个。为了使和最大,每一段中应选取那个值最大的数。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

bool has_same_sign(long long a, long long b) {
    return (a > 0 && b > 0) || (a < 0 && b < 0);
}

void solve() {
    int n;
    cin >> n;
    vector<long long> a(n);
    for (int i = 0; i < n; ++i) cin >> a[i];
    
    long long total_sum = 0;
    for (int i = 0; i < n; ++i) {
        long long current_val = a[i];
        int j = i;
        while (j < n && has_same_sign(a[i], a[j])) {
            current_val = max(current_val, a[j]);
            j++;
        }
        total_sum += current_val;
        i = j - 1;
    }
    cout << total_sum << endl;
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

D. Constant Palindrome Sum

给定长度为 $n$ 的数组,元素范围在 $[1, k]$。需要通过修改最少的元素,使得所有对 $(a_i, a_{n-i+1})$ 的和都等于某个常数 $x$。 对于每一对 $(a, b)$,设 $S = a + b$: 1. 和为 $S$:修改 0 次。 2. 和在 $[\min(a, b) + 1, \max(a, b) + k]$ 范围内:最少修改 1 次。 3. 其他范围($[2, 2k]$ 且不在上述区间):修改 2 次。 使用差分数组记录每个可能的 $x$ 值所需的修改次数,最后求前缀和找到最小值。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void solve() {
    int n, k;
    cin >> n >> k;
    vector<int> a(n);
    for (int i = 0; i < n; ++i) cin >> a[i];
    
    vector<int> diff(2 * k + 2, 0);
    for (int i = 0; i < n / 2; ++i) {
        int u = a[i], v = a[n - i - 1];
        int sum_val = u + v;
        
        // 默认所有位置都需要修改 2 次
        diff[2] += 2;
        diff[2 * k + 1] -= 2;
        
        // 修改 1 次的区间:[min(u,v)+1, max(u,v)+k]
        int L = min(u, v) + 1;
        int R = max(u, v) + k;
        diff[L] -= 1;
        diff[R + 1] += 1;
        
        // 修改 0 次的点:u+v
        diff[sum_val] -= 1;
        diff[sum_val + 1] += 1;
    }
    
    int min_ops = n;
    int current_ops = 0;
    for (int i = 2; i <= 2 * k; ++i) {
        current_ops += diff[i];
        min_ops = min(min_ops, current_ops);
    }
    cout << min_ops << endl;
}

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

E. Weights Distributing

给定带权无向图,求从 $a \to b \to c$ 的最短路径总权值。边权可以任意分配。 路径可以看作 $(b \to x) + (x \to a) + (x \to c)$。其中 $b \to x$ 段被走过了两次。 为了使总权值最小,应将最小的一组边权分配给 $b \to x$ 段,次小的一组边权分配给其余段。 方案: 1. 通过 BFS 计算 $a, b, c$ 到所有点 $i$ 的最短距离 $da[i], db[i], dc[i]$。 2. 对给定的边权进行排序并计算前缀和。 3. 枚举中间点 $x$,总权值为 $prefix[db[i]] + prefix[da[i] + db[i] + dc[i]]$。

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

const long long INF = 1e18;

void get_dist(int start, int n, vector<int>& d, const vector<vector<int>>& adj) {
    fill(d.begin(), d.end(), -1);
    d[start] = 0;
    queue<int> q;
    q.push(start);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int v : adj[u]) {
            if (d[v] == -1) {
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
    }
}

void solve() {
    int n, m, a, b, c;
    cin >> n >> m >> a >> b >> c;
    vector<long long> p(m);
    for (int i = 0; i < m; ++i) cin >> p[i];
    sort(p.begin(), p.end());
    
    vector<long long> pref(m + 1, 0);
    for (int i = 0; i < m; ++i) pref[i + 1] = pref[i] + p[i];
    
    vector<vector<int>> adj(n + 1);
    for (int i = 0; i < m; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    
    vector<int> da(n + 1), db(n + 1), dc(n + 1);
    get_dist(a, n, da, adj);
    get_dist(b, n, db, adj);
    get_dist(c, n, dc, adj);
    
    long long ans = INF;
    for (int i = 1; i <= n; ++i) {
        if (da[i] + db[i] + dc[i] > m) continue;
        ans = min(ans, pref[db[i]] + pref[da[i] + db[i] + dc[i]]);
    }
    cout << ans << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}
标签: Codeforces

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。