Codeforces Round #326 (Div. 2) 588ABC题解

本文提供了三道算法题目的解析及AC代码实现:A题通过处理价格波动最小化成本;B题寻找最大非平方整除因子;C题计算移除序列元素的最少次数。

题目链接:点击打开链接


A: 给出n天的需求和肉的价格, 问你满足每天的需求需要花费的最少买肉价格是多少.

脑洞题目, 因为肉价格是已知的, 所以对每个上升的子序列需求求和, 乘以最低价格, 然后累加起来就是答案.

AC代码:

#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
using namespace std;
const int MAXN = 1e5 + 5;
int n, a[MAXN], p[MAXN], ans, mi = 105;
int main(int argc, char const *argv[])
{
    scanf("%d", &n);
    for(int i = 0; i < n; ++i)
        scanf("%d%d", &a[i], &p[i]);
    ans += a[0] * p[0];
    mi = p[0];
    for(int i = 1; i < n; ++i)
        if(p[i] >= mi) ans += a[i] * mi;
        else {
            mi = p[i];
            ans += a[i] * mi;
        }
    printf("%d\n", ans);
    return 0;
}


B: 给一个数字, 让你输出这个数的一个因子, 要求这个因子尽可能大且不可被任何数的平方所整除.

根据数据范围, 暴力做就可以. 由于要尽可能的大, 所以保存因子的时候用了优先队列, 最后判断即可.

AC代码:

#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
#include "queue"
using namespace std;
const int MAXN = 1e6 + 10;
typedef long long ll;
ll n, p[MAXN], num;
priority_queue<ll> q;
void get_dis(ll x)
{
    for(ll i = 1; i * i <= x; ++i)
        if(x % i == 0) {
            q.push(i);
            q.push(x / i);
        }
}
int main(int argc, char const *argv[])
{
    scanf("%lld", &n);
    for(ll i = 2; i * i <= n; ++i)
        p[num++] = i * i;
    get_dis(n);
    while(!q.empty()) {
        bool flag = false;
        ll x = q.top();
        for(int i = 0; i < num; ++i)
            if(x % p[i] == 0) {
                q.pop();
                flag = true;
                break;
            }
        if(!flag) {
            printf("%lld\n", x);
            return 0;
        }
    }
    return 0;
}


C: 给出一个序列, 问你最少去除多少次可以使序列为空. 去除的条件是 2a1 + 2a2 + ... + 2ak = 2x

脑洞题目,. 记录序列中每个数的数目, 然后遍历一次, 每次操作使当前数除2加到后一个数, 如果为奇数那么ans就加1. 偶数则说明满足

件.

AC代码:

#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
using namespace std;
const int MAXN = 1e6 + 100;
int n, ans, a[MAXN];
int main(int argc, char const *argv[])
{
    scanf("%d", &n);
    for(int i = 0; i < n; ++i) {
        int x;
        scanf("%d", &x);
        a[x]++;
    }
    for(int i = 0; i < MAXN; ++i) {
            a[i + 1] += a[i] >> 1;
            ans += (a[i] & 1);
        }
    printf("%d\n", ans);
    return 0;
}


### 完美排列问题分析 对于 Codeforces Round 1007 (Div. 2) 中的 **B. Perfecto** 问题,目标是找到一个长度为 \( n \) 的完美排列。如果这样的排列存在,则输出该排列;否则输出 `-1`。 #### 题目解析 题目定义了一个“完美排列”,其条件如下: - 对于任意位置 \( i \),满足 \( |p_i - p_{i+1}| = 1 \) 或者 \( |p_i - p_{i+1}| = n-1 \)[^2]。 这意味着相邻两个元素之间的差值要么等于 1(即连续),要么等于 \( n-1 \)(即首尾相连)。 #### 解题方法 通过观察和归纳可以得出以下结论: - 当 \( n \% 3 == 0 \) 或 \( n \% 3 == 2 \) 时,无法构建出符合上述条件的完美排列。 - 而当 \( n \% 3 == 1 \) 时,可以通过特定构造方式生成所需排列。 具体实现逻辑如下: ```cpp #include <bits/stdc++.h> using namespace std; void solve() { int n; cin >> n; if (n % 3 != 1) { // 如果不符合模数条件 cout << "-1\n"; return; } vector<int> res(n); bool flag = true; // 控制交替模式 for(int i = 0;i < n;i++) { if(flag){ res[i] = i + 1; } else{ res[i] = ((n-i)+1)%n; if(res[i]==0)res[i]=n; } flag=!flag; } for(auto num : res){ cout<<num<<" "; } } int main(){ ios::sync_with_stdio(false); cin.tie(0); int t=1; while(t--){ solve(); } } ``` 此代码片段实现了基于输入大小 \( n \) 来判断是否存在合法解并输出相应结果的功能。 #### 关键点说明 - 判断依据来源于对不同余数值下能否形成循环结构的研究成果。 - 构造过程中采用交替填充策略来确保最终序列能够满足绝对差的要求。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值