【算法科目】2024年第二届全国大学生信息技术认证挑战赛 题解

news2024/9/27 17:31:11

图像压缩

曾经看到过,这是一道洛谷原题,很可惜我没做过,有点看不懂就没尝试。

原题链接:B3851 [GESP202306 四级] 图像压缩 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

因数分解

直接枚举就行了,从2开始找因子,到sqrt(n),从小到大能被除的话一定是素数。

假设a<b<c,且a和c是素数因子,b是合数因子。

由于合数可以由素数因子相乘得到:那么b=d+e,且d和e均小于等于sqrt(b),故从2到sqrt(n)遍历能除的除干净之后,除出来的必然是素数。

对于大于sqrt(n)部分的因子,合数因子必然能分解成小于sqrt(n)的部分,除完之后还有剩下的,那么剩下的就为素数。

Q:有没有可能剩下的素数有两个。

A:两个素数均大于sqrt(n),则乘积大于n,不合法。故最多一个。

最后考虑特殊情况,如果上面循环完了n还不为1,那么n就是素数。

#include <bits/stdc++.h>
#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define debug(a) cout<<#a<<"="<<a<<endl
#define fr first
#define se second
#define endl '\n'
using namespace std;

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

    map<int,int>f;

    int a=n;
    per(i,2,sqrt(n)){
        if(a%i==0){
            int cnt=0;
            while(a%i==0){
                a/=i;
                cnt++;
            }
            f[i]=cnt;
        }
    }

    if(a>1)f[a]++;

    auto it=f.rbegin();
    for(auto i:f){
        if(i.se==1){
            cout<<i.fr<<" ";
        }else{
            cout<<i.fr<<"^"<<i.se<<" ";
        }
        if(i!=*it){
            cout<<"* ";
        }
    }
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int t=1;
    while(t--)solve();
    return 0;
}

一个数可以分解数质数相乘。

更细化的,这些质数可以是偶数个或者奇数个。如 2 * 3 都只有一个,而 2^2*3,2有两个。

所以我们可以把质数分成 数量为奇数的 和 数量为偶数的。

根据从小到大能除除干净,除出来的是质数,我们可以先分离出数量为偶数的。

    per(i,2,sqrt(n)){
        int x=i*i;
        while(n%x==0)f[i]+=2,n/=x;
    }

假设一个平方质因子都没分离出来,那么n=a*b*c*d a,b,c,d为素数且均为一个。

所以只需要2~sqrt(n)遍历一次,大于sqrt(n)的只有一个,故如果n除完之后大于1,这就是那一个大于sqrt的数。

总复杂度sqrt(n)+sqrt(n),但是这样可以分离出所有的单个因子,有需要的话可以提供更多思路。

#include <bits/stdc++.h>
#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define debug(a) cout<<#a<<"="<<a<<endl
#define fr first
#define se second
#define endl '\n'
using namespace std;

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

    map<int,int>f;
    per(i,2,sqrt(n)){
        int x=i*i;
        while(n%x==0)f[i]+=2,n/=x;
    }

    per(i,2,sqrt(n)){
        if(n%i==0){
            f[i]++;
            n/=i;
        }
    }

    if(n>1)f[n]++;

    auto it=f.rbegin();
    for(auto i:f){
        if(i.se>=2){
            cout<<i.fr<<"^"<<i.se<<" ";
        }else cout<<i.fr<<" ";

        if(i!=*it){
            cout<<"* ";
        }
    }
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int t=1;
    while(t--)solve();
    return 0;
}

探险

这道题应该才是签到题。不过被榜单带歪了都是先做的 因数分解求和。

可以肯定的是,小理一定在某个洞穴停下,剩下的次数全部用来反复进入前面进入过的洞穴,且反复进入的洞穴一定是同一个,经验值最大的那一个。

那么只需要枚举所有情况就可以了。

#include <bits/stdc++.h>
#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define debug(a) cout<<#a<<"="<<a<<endl
#define fr first
#define se second
#define endl '\n'
using namespace std;

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

    vector<int> a(n+1),b(n+1);
    per(i,1,n)cin>>a[i];
    per(i,1,n)cin>>b[i];

    int f=0,res=0,ans=0;
    per(i,1,min(n,k)){
        int leave=k-i;//剩下的次数
        f+=a[i];//开洞穴累计的经验值
        res=max(res,b[i]);//前面开过的洞穴最大的那一个
        ans=max(ans,leave*res+f);//累计答案
    }

    cout<<ans<<endl;
}

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

最小乘积

这道题显然官方数据集弄错了,导致一个人都没有通过。

可以进行的操作:

1、ai<0 可以将 ai 替换成 [ai,0] 其中的一个。

2、ai>=0 可以将 ai 替换成 [0,ai] 其中的一个。(显然 0 不能做修改)

要求进行最少的操作,使得数组的乘积最小。

只需要记录一下正数,负数,0,的数量即可。

如果存在 0,显然不管怎么操作最后乘积都是0,则不需要操作。

如果不存在 0,若 负数 有奇数个,那么最终乘积为负数,不需要修改。

                         若 负数 有偶数个,那么乘积一定正数,任意一个改成0。

无人AC。

#include <bits/stdc++.h>
#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define debug(a) cout<<#a<<"="<<a<<endl
#define fr first
#define se second
#define endl '\n'
using namespace std;

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

    int pos=0,neg=0,zero=0;
    per(i,1,n){
        int tmp;
        cin>>tmp;
        if(tmp>0)pos++;
        else if(tmp<0)neg++;
        else if(tmp==0)zero++;
    }

    if(zero){
        cout<<0<<endl;
    }else{
        if(neg%2==0){
            cout<<1<<endl;
            cout<<1<<" "<<0<<endl;
        }else{
            cout<<0<<endl;
        }
    }
}

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

若此非正解请在评论区留言,否则建议大伙避雷该比赛,且本次全国赛算法科目只有120个左右参加,好少的人。

求和

一道哈人的模拟题。

思路比较简单,就是数字全部提取出来加在一起。

需要注意的是负号-,有可能作为分隔符使用。

如2-3,输出的是2+3=5

而2--3,输出的是2-3=-1

那么作为分割符的条件就很明显了,前面不能是数字。

由于输入没有告知多少行,且中间可能存在空行,所以我们使用getline来读入。

string s;
while(getline(cin,s))

本地调试的时候如果没有结果,请按下Ctrl+D,相当于输入文件末尾的EOF。

#include <bits/stdc++.h>
//#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define debug(a) cout<<#a<<"="<<a<<endl
#define fr first
#define se second
#define endl '\n'
using namespace std;

void solve(){
    string s;
    while(getline(cin,s)){
        int res=0,ans=0;
        bool havNum=false;
        int pos=1;//是否是正数

        if(s.empty())continue;//什么都没有输入直接跳过

        per(i,0,s.length()-1){
            if(s[i]>='0' and s[i]<='9'){
                havNum=true;
                res*=10;
                res+=s[i]-'0';
            }else if(s[i]=='-' and s[i+1]>='0' and s[i+1]<='9' and !(s[i-1]>='0' and s[i-1]<='9')){
                pos=-1;
            }else{
//                debug(res*pos);
                ans+=res*pos;
                pos=true;
                res=0;
            }
        }

        if(res)ans+=res*pos;//考虑最后结尾是数字,没有累加上的情况。
        if(havNum)cout<<ans<<endl;//字符串中至少有一个整数才能输出。
    }
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int t=1;
    while(t--)solve();
    return 0;
}

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

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

相关文章

python中的类与对象(3)

目录 一. 类的多继承 二. 类的封装 三. 类的多态 四. 类与对象综合练习&#xff1a;校园管理系统 一. 类的多继承 在&#xff08;2&#xff09;第四节中我们介绍了什么是类的继承&#xff0c;在子类的括号里面写入要继承的父类名。上一节我们只在括号内写了一个父类名&…

Latex中如何调整算法伪代码\begin{algorithm}的字体大小?

在LaTeX中&#xff0c;要调整algorithm环境&#xff08;通常与algorithmic、algorithmicx、algorithm2e等包一起使用来编写伪代码&#xff09;中的字体大小&#xff0c;你可以使用\small、\footnotesize、\tiny等命令来减小字体大小&#xff0c;或者使用\large、\Large、\LARGE…

简单实现文字滚动效果-CSS版本

先看看效果 话不多说直接上代码 <template><div class"main"><div class"scroll-region"><div class"swiper-scroll-content"><span class"list-btn" v-for"(item, index) in overviewList" :…

【重温设计模式】命令模式及其Java示例

命令模式的介绍 在我们的编程世界中&#xff0c;设计模式如同一盏指路明灯&#xff0c;它们是前人智慧的结晶&#xff0c;为我们照亮了解决复杂问题的路径。 其中&#xff0c;命令模式是一种行为设计模式&#xff0c;其主要的目标是将操作封装到对象中。这种模式的一个显著特点…

基于springboot+vue的图书电子商务网站

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

数据修改

Oracle 目录 数据修改 将员工编号的 7369 的员工工资修改为 810&#xff0c;佣金改为 100 将工资最低的员工工资修改为公司的平均工资 将所有在 1981 年雇佣的员工的雇佣日期修改为今天&#xff0c;工资增长 20% 数据的更新操作 Oracle从入门到总裁:https://blog.csdn.n…

学习人工智能的方法及方向!

目录 一、第一部分&#xff1a;了解人工智能 二、人工智能学习路线图 三、职业规划 四、未来展望 五、总结 在这个信息爆炸的时代&#xff0c;想要系统性地学习人工智能&#xff08;AI&#xff09;并找到对应方向的工作&#xff0c;你需要一个明确的学习路径和职业规划。本…

【latex】\IEEEpubid版权声明与正文内容重叠

问题描述 撰写IEEE Trans论文时&#xff0c;出现版权声明文字\IEEEpubid与正文内容重叠的问题&#xff1a; 原因分析&#xff1a; 在使用模板时&#xff0c;不小心将以下命令删除了&#xff1a; \IEEEpubidadjcol 解决方案&#xff1a; 在需要换页的位置附近添加以上命令&…

投影和定义投影的区别

Arcmap中关于投影的工具有四个&#xff0c;分别是定义投影、投影、投影栅格、批量投影。这四个工具既有相同之处也有不同之处&#xff0c;下面我将一一介绍。 ①定义投影&#xff1a;Arcmap中关于定义投影工具是这样描述的&#xff1a;“所有地理数据集均具有一个用于显示、测…

【LeetCode题解】2859. 计算 K 置位下标对应元素的和+938. 二叉搜索树的范围和+1028. 从先序遍历还原二叉树(三种方法:栈+递归+集合)

文章目录 [2859. 计算 K 置位下标对应元素的和](https://leetcode.cn/problems/sum-of-values-at-indices-with-k-set-bits/)思路&#xff1a; [938. 二叉搜索树的范围和](https://leetcode.cn/problems/range-sum-of-bst/)思路&#xff1a;写法一&#xff1a;在中间累加写法二…

从零开始学习Netty - 学习笔记 -Netty入门【半包,黏包】

Netty进阶 1.黏包半包 1.1.黏包 服务端代码 public class HelloWorldServer {private static final Logger logger LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());public static void main(String[] args) {NioEventLoopGroup bossGroup new NioEventL…

Linux多线程控制:深入理解与应用(万字详解!)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;どうして (feat. 野田愛実) 0:44━━━━━━️&#x1f49f;──────── 3:01 &#x1f504; ◀️ ⏸ ▶️ …

基于redis实现【最热搜索】和【最近搜索】功能

目录 一、前言二、分析问题三、针对两个问题&#xff0c;使用redis怎么解决问题&#xff1f;1、字符串String2、列表List3、字典Hash4、集合Set5、有序集合ZSet6、需要解决的五大问题 四、编写代码1.pom依赖2.application.yml配置3.Product商品实体4.用户最近搜索信息5.redis辅…

C-V2X系列:C-V2X芯片及模组整理总结

C-V2X、车路协同、车联网、智能网联车学习 C-V2X芯片及模组整理总结

Typora旧版链接(Win+Mac+Linux版)

记得点赞本文&#xff01;&#xff01;&#xff01; 链接&#xff1a;https://pan.baidu.com/s/1IckUvQUBzQkfHNHXla0zkA?pwd8888 提取码&#xff1a;8888 –来自百度网盘超级会员V7的分享

2.模拟问题——4.日期问题

日期问题难度并不大&#xff0c;但是代码量非常大&#xff0c;需要较高的熟练度&#xff0c;因此需要着重练习&#xff0c;主要涉及数组和循环两个方面的知识点&#xff0c;需要熟练的测试代码。 两个经典题型 闰年 闰年满足以下两个条件的任意一个 能够被400整除不能够被1…

Golang Vs Java:为您的下一个项目选择正确的工具

Java 首次出现在 1995 年&#xff0c;由 James Gosling 和 Sun Microsystems 的其他人开发的一种新编程语言。从那时起&#xff0c;Java 已成为世界上最受欢迎和广泛使用的编程语言之一。Java 的主要特点包括其面向对象的设计、健壮性、平台独立性、自动内存管理以及广泛的内置…

JavaSec 基础之 JNDI 注入

文章目录 JNDI简介JNDI 支持的服务协议JNDI 注入JNDI 复现修复 JNDI 简介 JNDI(Java Naming and Directory Interface)是一个应用程序设计的 API&#xff0c;一种标准的 Java 命名系统接口。JNDI 提供统一的客户端 API&#xff0c;通过不同的访问提供者接口JNDI服务供应接口(…

武器大师——操作符详解(下)

目录 六、单目操作符 七、逗号表达式 八、下标引用以及函数调用 8.1.下标引用 8.2.函数调用 九、结构体 9.1.结构体 9.1.1结构的声明 9.1.2结构体的定义和初始化 9.2.结构成员访问操作符 9.2.1直接访问 9.2.2间接访问 十、操作符的属性 10.1.优先性 10.2.结合性 …

Ubuntu20.04使用XRDP安装原生远程桌面

Ubuntu20.04使用XRDP安装原生远程桌面 1.安装gnome桌面 # 如果没有更新过源缓存&#xff0c;先更新一下 sudo apt update# 安装gnome桌面 # 可选参数 --no-install-recommends&#xff0c;不安装推荐组件&#xff0c;减少安装时间和空间占用 sudo apt install ubuntu-desktop…