Codeforces Educational 179(ABCDE)

news2025/6/9 15:24:58

前言

byd这组题纯靠感觉是吧…^_^¦¦¦

b题赛时举了无数个例子都没想明白,然后一直卡到结束,后面题都没看到,结果补题的时候c题d题直接秒了…-_-|| 

A. Energy Crystals

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

void solve()
{
    int x;
    cin>>x;

    priority_queue<int,vector<int>,greater<int>>pq;

    for(int i=0;i<3;i++)
    {
        pq.push(0);
    }

    int ans=0;
    while(!pq.empty())
    {
        int cur=pq.top();
        pq.pop();
        ans++;

        if(!pq.empty())
        {
            int next=pq.top()*2+1;
            if(next<x)
            {
                pq.push(next);
            }
        }
    }

    cout<<ans<<endl;
}

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

上来这个题就花了半个小时,但好歹观察了半天观察出来了……

思路就是准备一个小根堆,维护三个晶体能量的最小值,然后在往上增加的过程中最优解肯定是让三者的最小值增加到能增加到的最大值。接着就是每次拿堆顶元素,让最小值往上跳,操作数ans+1。之后若堆不为空,就每次往第二小,即当前堆顶的两倍加一跳。若比目标x小,就再加入堆顶,等着后续去跳。否则就当作直接跳到x,不往堆里加即可。

B. Fibonacci Cubes

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

const int MAXN=10+5;

//数列值
vector<int>fib(MAXN);

void build(int n)
{
    fib[1]=1;
    fib[2]=2;

    for(int i=3;i<=n;i++)
    {
        fib[i]=fib[i-1]+fib[i-2];
    }
}

void solve()
{
    int n,m;
    cin>>n>>m;

    //生成斐波那契数列
    build(n);

    for(int i=0,w,l,h;i<m;i++)
    {
        //重点:斐波那契数列的性质
        //…… 13 8 5 3 2 1
        //对于最大的立方体,只有长宽高都大于等于的时候才能放
        //若底面较大,高度不够了
        //      因为13=8+5,所以只需要判断剩余底面上的空间是否大于8,之后8和5可以并列放在13旁边
        //      又因为5=3+2,8=5+3,所以在边长为5的立方体上,必然可以放下3和2,此时5+3高度正好8
        //      最后在边长为2的立方体上必然可以放下1
        //若高度较大,底面不够了
        //      同样因为13=8+5,所以只要上方高度大于等于8,就存在8×13×13的区域
        //      此时和上个情况相同,必然可以放下后续所有的

        //题目本身已经定义了哪面是底!!!!!
        cin>>w>>l>>h;

        if(w<l)//让w更大
        {
            swap(w,l);
        }

        if(h<fib[n]||l<fib[n]||w<fib[n])//放不下
        {
            cout<<0;
        }
        else if(w>=fib[n]+fib[n-1])//底面上放下fib[n]后存在fib[n-1]×fib[n]×fib[n]的区域
        {
            cout<<1;
        }
        else if(h>=fib[n]+fib[n-1])//高度满足
        {
            cout<<1;
        }
        else
        {
            cout<<0;
        }

    }
    cout<<endl;
}

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

这个题的重点是斐波那契数列的性质对放置的影响。虽然赛时想到了要联系斐波那契数列的性质,但真没想到这个结论……

首先,这个题里已经明确给出了哪条边是长宽高,不需要自己判断!!!(nnd赛时没看到这个,一直在想如何放置之后判断长宽高,浪费了不少时间……)读入数据之后,可以默认w大于l,如果相反就交换。然后,因为肯定从最大的开始放,所以若三条边中有一条比这个最大值还小,那直接就是不可能放出来,直接输出0即可。

之后的思路是重点,举个例子,当n=6时,此时数列从大到小为13,8,5,3,2,1。此时可以分底面比较大、高度比较小和高度比较大、底面比较小两种情况讨论。

对于第一种情况,在底面上放下13×13×13后,因为高度比较小,所以只能在这个正方体旁边的底面上放后续立方体。而根据斐波那契数列的性质,13=8+5,所以考虑极限情况,即若底面剩余的空间只能放下8×8×8的,那么这个立方体和5×5×5的立方体必然可以整齐地贴在13×13×13的立方体旁边。然后因为8=5+3,所以即使底面剩余的空间放不下了,3×3×3的立方体仍可以放在5×5×5的立方体上,和8×8×8的立方体的高对齐。同理,2×2×2的立方体也能贴着3×3×3的立方体正好和5×5×5的立方体的边对齐,最后1×1×1的也可以放在2×2×2的上面和3×3×3的高对齐。

第二种情况里,因为底面比较小,所以极限情况是在放下13×13×13的立方体后底面放不下剩下的立方体了。同样因为13=8+5,所以若剩余高度能放下8×8×8的,那么5×5×5的就能靠着8×8×8的和13×13×13的边对齐。之后还是因为8=5+3,所以3×3×3的可以放在5×5×5的上方和8×8×8的高对齐。接下来的过程就和第一种情况类似了。

所以,只需要判断底面两边的最大值w或者高度h是否大于等于fib[n]+fib[n-1]即可,满足的话就必然可以放下,输出1,否则就是0。

C. Equal Values

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

void solve()
{
    int n;
    cin>>n;
    vector<int>a(n+1);
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    
    ll ans=1e18;
    for(int i=1;i<=n;i++)
    {
        ll left=(i-1)*(ll)a[i];
        while(i+1<=n&&a[i+1]==a[i])
        {
            i++;
        }
        ll right=(n-i)*(ll)a[i];
        ans=min(ans,left+right);
    }
    cout<<ans<<endl;
}

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

蚌埠住了,感觉cd比b简单多了……

这个题直接观察测试用例就能发现方法了。要想把整个数组刷成一样的,那么对于每个数,要把数组刷成和当前数一样就是往左刷一次再往右刷一次。而为了让刷的次数减小,所以若遇到几个连续相等的数,那就让最左侧的往左刷,最右侧的往右刷,中间天然相等的部分就可以不用刷了。

所以方法就是来到每个数时先统计一下往左刷的代价,再跳到这一段连续相等的最后一个数,计算一下往右刷的代价,最后统计代价left和right之和的最小值即可。

D. Creating a Schedule

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

void solve()
{
    int n,m;
    cin>>n>>m;
    vector<int>c(m);
    for(int i=0;i<m;i++)
    {
        cin>>c[i];
    }

    sort(c.begin(),c.end());

    //这代码太抽象了
    
    for(int i=0,p=0;i<n;i+=2,p++)
    {
        for(int j=0;j<((n-i)>1?2:1);j++)
        {
            bool t=j%2;
            for(int k=0;k<6;k++)
            {
                cout<<(t?c[p]:c[m-p-1])<<" ";
                t=!t;
            }
            cout<<endl;
        }
    }
}

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

这个题真属于是贪心到极致了……

因为随便输出一种即可,观察测试用例就能发现,只需要让这n个班级两两一组,每组在两个教室交替着上课即可。又因为要求跨越的楼层最大,所以对于每一组两个班,让他们在序号最大和最小的两个教室来回走即可。

所以方法就是先对教室从小到大排序,然后枚举这n个班级,注意每次i+=2往后跳两个表示一组两个班级。接着当剩余班级大于1时,就说明可以合并成一组,那就循环两次,每次交替输出去上课的教室。而对于每一组去上课的教室,就是设置一个指针p,每过完一组p往后跳一步。当前组上课的两个教室就是p位置的教室和m-p-1位置的教室,即剩下空闲的教室的最大最小值。

要注意的就是若只剩下一个班级,那只需要循环一次即可。

E. Changing the String

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

void solve()
{
    int n,q;
    cin>>n>>q;
    string s;
    cin>>s;

    //需要考虑操作的先后次序!!
    //字符类型转数字方便操作

    vector<int>b(q);
    for(int i=0;i<q;i++)
    {
        char x,y;
        cin>>x>>y;
        b[i]=(x-'a')*10+y-'a';//转数字
    }

    //字符串转数字
    vector<int>a(n);
    for(int i=0;i<n;i++)
    {
        a[i]=s[i]-'a';
    }

    //用set存第几次操作
    vector<set<int>>c(23);
    for(int i=0;i<q;i++)
    {
        c[b[i]].insert(i);
    }

    //从高位到低位考虑
    for(int i=0;i<n;i++)
    {
        //是'a'不改
        if(a[i]==0)
        {
            continue;
        }

        //是'b'
        if(a[i]==1)
        {
            //能一步转'a'
            if(!c[10].empty())
            {
                a[i]=0;
                c[10].erase(c[10].begin());//删第一次
            }
            else if(!c[12].empty()&&!c[20].empty())//不能一步转 -> "bc""ca"
            {
                auto iter=c[20].lower_bound(*c[12].begin());//删"bc"后的第一个"ca"
                if(iter!=c[20].end())//后续有"ca"才改
                {
                    a[i]=0;
                    c[12].erase(c[12].begin());
                    c[20].erase(iter);
                }
            }
        }
        else//是'c'
        {
            if(!c[20].empty())//能一步转'a'
            {
                a[i]=0;
                c[20].erase(c[20].begin());
            }
            else if(!c[21].empty()&&!c[10].empty()
            &&c[10].lower_bound(*c[21].begin())!=c[10].end())//不能一步转 -> "cb""ba"
            {
                auto iter=c[10].lower_bound(*c[21].begin());
                a[i]=0;
                c[21].erase(c[21].begin());
                c[10].erase(iter);
            }
            else if(!c[21].empty())//不能转到'a' -> 只能转到'b'
            {
                a[i]=1;
                c[21].erase(c[21].begin());
            }
        }
    }

    for(int i=0;i<n;i++)
    {
        cout<<char(a[i]+'a');
    }
    cout<<endl;
}

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

啧,这个题自己补的时候思路其实对了,但就是没考虑到操作的顺序也会产生影响,错解里直接读相应操作出现的次数,然后就WA2了……

整体思路就是考虑所有操作出现的组合,三个字母无非就是“ab”“ac”“ba”“bc”“ca”“cb”这六种。而为了让字典序最小,所以就是从高位到低位依次考虑。来到每一位时,首先只要能变成“a”肯定变“a”,变不到的话再考虑“b”的情况。所以对于转成“a”而言,可以“ba”“ca”直接一步转,还可以经过“bc”"ca"和“cb”“ba”这两种情况两步转到“a”。那么之后的思路就是,如果当前位为“a”就直接不看去下一位。当不是“a”时,如果能一步直接转到“a”就直接转,不能的话再考虑两步转的操作。而对于两步转的操作,如果第一种情况“bc”"ca"有一种不存在就不能转,而第二种情况即使“ba”不存在,也可以通过“cb”将“c”转成“b”。

所以实现方法就是先把操作转成一个两位数,接着再把字符串也转成数方便计算。为了记录每种操作出现的位置,所以考虑用一个set存对应操作的那个两位数的所有出现位置。之后从高位到低位遍历字符串,是“a”就跳过,不是“a”的话才考虑。首先如果能一步转成就直接转,不能的话可以用一个lower_bound在第二步的所有操作位置的set里找大于等于第一步操作最早出现的位置。若此时迭代器不等于end说明有第二步操作,那就可以转,最后每次把第一步操作的begin和第二步操作的iter删除。这样就能保证不打乱操作顺序。

总结

思维还是不够,多想多练吧……

END

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2405519.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python:Tkinter 开发邮件客户端,能编写邮件,发送邮件带附件

Python Tkinter 邮件客户端 下面是一个使用 Python Tkinter 开发的简单邮件客户端&#xff0c;支持编写邮件和发送邮件功能&#xff1a; 功能说明 这个邮件客户端包含以下功能&#xff1a; 邮件编写功能&#xff1a; 收件人地址输入抄送地址输入邮件主题输入邮件正文编辑区&…

深入解析Java21核心新特性(虚拟线程,分代 ZGC,记录模式模式匹配增强)

文章目录 前言一、虚拟线程 (Virtual Threads - JEP 444) - 并发的革命1.1 解决的核心问题&#x1f3af;1.2 工作原理与核心机制⚙️1.3 使用详解与最佳实践&#x1f6e0;️1.4 注意事项⚠️1.5 总结 &#x1f4da; 二、分代 ZGC (Generational ZGC - JEP 439) - 低延迟新高度2…

免费批量去水印工具 - 针对文心一言生成图片

免费批量去水印工具 - 针对文心一言生成图片 工具介绍 这是一款免费的批量去水印工具&#xff0c;专门针对文心一言生成的图片进行处理。通过简单的操作&#xff0c;您可以快速去除图片中的水印。 下载链接 您可以通过以下网盘链接下载工具&#xff1a; 链接: https://pa…

在WPS中如何启用宏VBA wps.vba.exe下载和安装

首先我们点击导航栏中的【工具】&#xff0c;点击左侧 运行宏&#xff0c;根据提示 点击 立即加载。加载卡在50%时间比较长&#xff0c;耐心等待。 关闭wps重新打开后&#xff0c; word和xls表格都可以使用了。 如果电脑无法联网&#xff0c;需要提前下载 WPS VBA插件 WPS VB…

Hardware-Efficient Attention for Fast Decoding

TL;DR 2025 年普林斯顿大学提出的硬件友好 attention 设计&#xff0c;在 MQA/GQA 与 deepseek 提出的 MLA 基础之上继续优化&#xff0c;提出 Grouped-Tied Attention (GTA) 和 Grouped Latent Attention (GLA)&#xff0c;实现更高推理效率的同时也能保持较好的模型效果。 …

LLMs 系列科普文(13)

十三、AlphaGO 提到强化学习的历史&#xff0c;不得不提到 alphago&#xff0c;如果你不记得这是什么了&#xff0c;那你是否还曾记得&#xff0c;早些年 AI 已经可以在围棋中击败人类选手了。 AlphaGO 系统又 DeepMind 公司开发&#xff0c;你可以在网络上找到当初人机大战的…

element-plus 单选组件 el-radio,选不上,又没报错,直接复制官网也不行解决方案

在使用 Vue 框架开发项目时&#xff0c;Element UI 是常用的组件库。最近在开发中遇到了 Element 单选框组件el-radio的双向绑定问题&#xff0c;直接复制element官网上的的案例下来也是不得&#xff0c;经过调试和探索&#xff0c;终于找到了解决方案&#xff0c;特此记录分享…

idea 启动jar程序并调试

添加一个JAR 应用程序&#xff0c;填写以下内容&#xff1a; JAR路径&#xff1a;填写你要启动的jar程序的绝对路径 虚拟机选项&#xff1a;-Xmx1G -Xms1G -agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005 程序实参&#xff08;可选&#xff0c;minecraft专用…

CSS 轮廓(Outline)与边框(Border)的深度解析

在 CSS 中&#xff0c;轮廓&#xff08;outline&#xff09;和边框&#xff08;border&#xff09;是两个用于装饰元素的重要属性&#xff0c;但它们在功能、渲染机制和应用场景上存在显著差异。下面从多个维度进行详细对比&#xff1a; 一、基础定义与语法差异 边框&#xf…

Docker 部署 Python 的 Flask项目

文章目录 一、构建运行 Docker 容器1. 查找合适镜像2.本地docker 拉取镜像3.项目配置1. python项目下生成 requirements.txt 依赖文件2. 生成Dockerfile文件3.忽略不必要文件4. 构建镜像 4. 运行容器5.测试 二、常见问题与解决方案 一、构建运行 Docker 容器 1. 查找合适镜像 …

Vue入门到实战之第一篇【超基础】

Vue入门到实战之第一篇 学习路线1. Vue 概念1.1 Vue 是什么 2. 创建Vue实例&#xff0c;初始化渲染3. 插值表达式 {{ }}4. Vue响应式特性5. 开发者工具 学习路线 1. Vue 概念 1.1 Vue 是什么 概念&#xff1a; Vue是一个用于 构建用户界面1 的 渐进式2 框架3 1&#xff1a;基…

实时数据分析的技术架构:Lambda vs Kappa架构选择

文章目录 引言:实时数据分析架构的重要性Lambda架构深度解析Kappa架构技术特性架构对比分析维度性能与可扩展性评估技术栈选型指南实际应用场景分析成本效益对比模型混合架构与演进策略企业级决策框架最佳实践与案例研究技术趋势与未来展望引言:实时数据分析架构的重要性 在…

springboot2.x升级springboot3.x

springboot2.x升级springboot3.x 背景升级jdk版本为17以上springboot版本修改javax包更新mybatis-plus升级swagger升级springdocspringdoc配置 背景 当前项目是springboot2.5.9版本的springbootmybatis-plus项目&#xff0c;需要升级到springboot3.5.0项目。 升级jdk版本为17…

Python训练打卡Day43

复习日 1.卷积神经网络的基本概念 2.kaggle找到一个图像数据集&#xff0c;用cnn网络进行训练并且用grad-cam做可视化 进阶&#xff1a;并拆分成多个文件 tips:注册kaggle的注意事项 安装插件&#xff1a;Header Editor 然后打开扩展选项&#xff1a; 输入网址&#xff1a;ht…

227.2018年蓝桥杯国赛 - 交换次数(中等)- 贪心

227. 交换次数&#xff08;贪心&#xff09; 1. 2018年蓝桥杯国赛 - 交换次数&#xff08;中等&#xff09; 标签&#xff1a;2018 暴力 国赛 1.1 题目描述 IT 产业人才需求节节攀升。业内巨头百度、阿里巴巴、腾讯&#xff08;简称 BAT &#xff09;在某海滩进行招聘活动。…

STM32入门学习之系统时钟配置

1. 时钟就是单片机的心脏。单片机根据时钟频率来控制每个部件的工作&#xff0c;时钟是单片机的脉搏&#xff0c;决定了每条命令运行的速率&#xff0c;没有时钟单片机将停止工作。 如何理解“时钟决定了单片机每条命令运行的速率”&#xff1f; 首先需要去理解单片机中的时…

【ArcGIS Pro微课1000例】0072:如何自动保存编辑内容及保存工程?

文章目录 一、自动保存编辑内容二、自动保存工程在使用ArcGIS或者ArcGIS Pro时,经常会遇到以下报错,无论点击【发送报告】,还是【不发送】,软件都会强制退出,这时如果对所操作没有保存,就会前功尽弃。 此时,自动保存工作就显得尤为重要,接下来讲解两种常见的自动保存方…

AU音频软件|Audition 2025网盘下载与安装教程指南

说起AU&#xff0c;有些小伙伴可能第一印象是化学元素金&#xff08;Aurum&#xff09;。实际上&#xff0c;本文要介绍的AU&#xff0c;全称是Adobe Audition&#xff0c;是一款专业音频编辑和混音软件‌&#xff0c;广泛应用于音乐制作、广播、电影及视频声音设计等领域。 目…

网络编程(TCP编程)

思维导图 1.基础流程 流程图中是TCP连接的基础步骤&#xff0c;其他操作都是在此基础上进行添加修改。 2.函数接口 2.1 创建套接字&#xff08;socket&#xff09; int socket(int domain, int type, int protocol); 头文件&#xff1a;#include <sys/types.h> …

热成像实例分割电力设备数据集(3类,838张)

在现代电力系统的运维管理中&#xff0c;红外热成像已经成为检测设备隐患、预防故障的重要手段。相比传统可见光图像&#xff0c;红外图像可揭示设备温度分布&#xff0c;从而更直观地反映过热、老化等问题。而在AI赋能下&#xff0c;通过实例分割技术对热成像中的电力设备进行…