当前位置: 首页 > news >正文

河南萌新联赛2025第(四)场【补题】

目录

  • A-完美序列
    • 解题思路
    • AC代码
  • C-合并石子
    • 解题思路
    • AC代码
  • G-封闭运算
    • 解题思路
    • AC代码
  • J-故障机器人的完美牌组
    • 解题思路
    • AC代码
  • L-故障机器人的完美遗物
    • 解题思路
      • 1. 数学原理(题解核心)
      • 2. 实现思路
    • AC代码

A-完美序列

题目链接
在这里插入图片描述

解题思路

所谓完美序列,就是让我们找给定的序列a中,选任意元素任意排列顺序,能组成最长的一个满足在这里插入图片描述
的序列的长度。那么我们可以用哈希表mp记录每个数字的个数,然后遍历可能的和的值2~10000,第二层循环从1 ~i/2,为了缩短时间同时防止重复记录,然后再令y=i-j,看满足这个条件的数有多少个,如果他的值和j相等,组合对数就加mp[j]/2,否则就取二者个数的最小值,最后更新一下最大值ans。输出即可。

AC代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int N=2e5+5;
const int inf=5000;
int n,num,mp[inf+10];
void solve()
{cin>>n;for(int i=1;i<=n;i++)cin>>num,mp[num]++;int ans=0;for(int i=2;i<=10000;i++){int res=0;for(int j=1;j<=i/2;j++){int x=i-j;if(x>inf)continue;if(x==j)res+=mp[x]/2;elseres+=min(mp[x],mp[j]);}ans=max(res,ans);}cout<<ans*2;	
}
signed main()
{IOS;int _=1;
//	cin>>_;while(_--)solve();return 0;
}

C-合并石子

在这里插入图片描述

解题思路

这道题我是分别记录位置i的左边所有数到达它需要的步数和右边所有数需要到达他的总步数,最后再将二者相加就是所有石子需要到达他的总步数。通过前缀和记录每个位置需要移动的石子个数,(数字+k-1)/k是向上取整的意思,再将每个位置的步数累加。然后遍历筛选一个最小的总和,ans初始值不能赋INT_MAX,不然会wa一半。。。因为题目中数字较大,所以初值赋1e18.

AC代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int N=1e6+6;
int n,k,a[N],b[N],c[N],s1[N],s2[N],l[N],r[N];
void solve()
{cin>>n>>k;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<=n;i++)l[i]=l[i-1]+a[i];for(int i=n;i>=1;i--)r[i]=r[i+1]+a[i];for(int i=1;i<=n;i++)s1[i]=s1[i-1]+(l[i]+k-1)/k; for(int j=n;j>=1;j--)s2[j]=s2[j+1]+(r[j]+k-1)/k;int ans=1e18;for(int i=1;i<=n;i++)ans=min(ans,s1[i-1]+s2[i+1]);cout<<ans;
}
signed main()
{IOS;int _=1;
//	cin>>_;while(_--)solve();return 0;
}

G-封闭运算

题目链接
在这里插入图片描述

解题思路

将原有的值都标记,数据范围很小,开双层循环遍历,如果二者异或值在原数组中不存在就输出”NO"如果全都存在就输出“YES".

AC代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int N=106;
int n,a[N];
map<int,int>mp;
void solve()
{cin>>n;int f=1;for(int i=1;i<=n;i++)cin>>a[i],mp[a[i]]++;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){int x=a[i]|a[j];if(mp[x]==0){f=0;break;}}if(!f)break;}if(f)cout<<"YES";elsecout<<"NO";
}
signed main()
{IOS;int _=1;
//	cin>>_;while(_--)solve();return 0;
}

J-故障机器人的完美牌组

题目链接
在这里插入图片描述

解题思路

简单的规律题,不过我错了很多发,第一看错题了,第二考虑少了。
首先如果是1,特判直接输出。
否则就从2~n找到最大值mx和最大值所在的位置j,然后看这个最大值是不是等于0,如果是,就不做处理,因为处理了不仅没有数变大而且长度会变小字典序就变小了。如果不是0,就将j标记,a[1]=a[1]+a[j],输出n-1,然后输出剩下的数,便利到j时不输出,因为已经用掉了。

AC代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int N=1e6;
int n,a[N],mx=-1e10,j;
unordered_map<int,int>b;
void solve()
{cin>>n;for(int i=1;i<=n;i++)cin>>a[i],b[a[i]]++;if(n==1){cout<<n<<endl;cout<<a[1]<<endl;return ;}for(int i=2;i<=n;i++){if(a[i]>=mx){mx=a[i];j=i;}}if(mx!=0){cout<<n-1<<endl;cout<<a[1]+mx<<" "; for(int i=2;i<=n;i++){if(i!=j)cout<<a[i]<<" ";}	}else{cout<<n<<endl;for(int i=1;i<=n;i++)cout<<a[i]<<" ";}}
signed main()
{IOS;int _=1;
//	cin>>_;while(_--)solve();return 0;
}

L-故障机器人的完美遗物

题目链接
在这里插入图片描述

解题思路

这道题的核心是判断一个数是否为“完美遗物”,并计算所有完美遗物的价值之和。完美遗物的定义是:该数的因数个数是质数且不等于 2。首先筛出可以开平方的数,这样它的因数一定是奇数个,就有可能是质数。

1. 数学原理(题解核心)

根据**数论唯一分解定理**,任何正整数 ( n ) 可分解为素数幂的乘积:[ n = \prod_{i=1}^k p_i^{\alpha_i} \quad (p_i \text{ 是素数,} \alpha_i \text{ 是正整数}) ]其**因数个数** ( d(n) ) 的计算公式为:[ d(n) = \prod_{i=1}^k (\alpha_i + 1) ]

要让 ( d(n) ) 是质数且 ≠ 2,需满足:

  • 因数个数的乘积结果是质数 → 乘积中只能有一个因子(否则质数相乘会得到合数)。
  • 因此,( n ) 的素因数分解形式必须是 ( n = a^{b-1} )(其中 ( a ) 是素数,( b ) 是质数且 ( b \neq 2 ) )。此时:
    [ d(n) = (b-1 + 1) = b ]
    ( b ) 是质数且 ≠ 2,满足“完美遗物”条件。

2. 实现思路

(1)预处理素数(prime 函数)
埃氏筛预处理出一定范围(如 ( 10^6 ) )内的素数,后续用于快速分解因数。

(2)因数个数计算(con 函数)
对输入的数 ( x ),先判断是否为平方数(因为完美遗物的形式是 ( a^{b-1} ),等价于平方数的变形)。若为平方数,对其平方根 ( \text{sqrt}(x) ) 做素因数分解,计算因数个数:

  • 分解平方根的素因数,得到各素因子的指数 ( d )。
  • 因数个数公式变为 ( \prod (2d + 1) )
    (因为原数是平方根的平方,指数翻倍)。

(3)筛选完美遗物(solve 函数)
遍历所有遗物值:

  • 先判断是否为平方数(否则不可能满足 ( n = a^{b-1} ) 形式)。
  • 对平方根分解,计算因数个数 ( f )。
  • 检查 ( f ) 是否是质数且 ≠ 2,若是则累加价值。

(1)埃氏筛预处理素数

const int N = 1e6 + 5000;
int a[N], b[N], q, k = 0; 
void prime() {a[1] = 1; // 1 不是素数for (int i = 2; i < N; i++) {if (a[i] == 0) b[++k] = i; // 记录素数for (int j = 1; j <= k && i * b[j] < N; j++) {a[i * b[j]] = 1; // 标记非素数if (i % b[j] == 0) break; // 保证每个合数只被最小素因子筛掉}}
}
  • a[] 标记是否为素数,b[] 存储素数列表。
  • 埃氏筛的核心是“用已知素数标记其倍数”,保证效率。

(2)因数个数计算(con 函数)

int con(int x) {if (x == 1) return 1; int c = 1; for (int i = 1; i <= k; i++) { int p = b[i]; if (p * p > x) break; // 超过平方根,无需继续if (x % p == 0) { int d = 0; while (x % p == 0) { // 分解出所有 p 的因子x /= p; d++; }c *= (d * 2 + 1); // 原数是平方数,指数翻倍后计算因数个数}}if (x > 1) c *= 3; // 剩余大素数因子(指数为1,翻倍后指数为2,d=1 → 2*1+1=3)return c; 
}

(3)主函数(solve 函数)

void solve() {int n, sum = 0; prime(); // 预处理素数cin >> n; vector<int> e(n + 1); for (int i = 1; i <= n; i++) cin >> e[i]; for (int i = 1; i <= n; i++) { int x = e[i]; int ii = sqrt(x); if (ii * ii != x) continue; // 不是平方数,直接跳过int f = con(ii); // 计算平方根的因数个数(即原数的因数个数)if (a[f] == 0 && f > 2) { // 因数个数是素数且 ≠2sum += x; }}cout << sum << endl; 
}
  • 先筛出平方数(非平方数不可能满足完美遗物条件)。
  • 对平方数,通过 con 计算因数个数,再判断是否为“质数且 ≠2”,若是则累加价值。

AC代码

#include<bits/stdc++.h>
#define int long long
using namespace std;const int N = 1e6 + 5000;
int a[N], b[N], k = 0; // a数组标记是否为素数,b数组存储素数// 埃氏筛法预处理素数
void prime() {a[1] = 1; // 1不是素数for (int i = 2; i < N; i++) {if (a[i] == 0) {b[++k] = i; // 记录素数}// 标记非素数for (int j = 1; j <= k && i * b[j] < N; j++) {a[i * b[j]] = 1;if (i % b[j] == 0) break; // 优化,避免重复标记}}
}// 计算x的因数个数相关值(针对平方数的平方根)
int con(int x) {if (x == 1) return 1;int c = 1;for (int i = 1; i <= k; i++) {int p = b[i];if (p * p > x) break; // 超过平方根,无需继续if (x % p == 0) {int d = 0;// 分解出所有p的因子while (x % p == 0) {x /= p;d++;}c *= (d * 2 + 1); // 计算因数个数}}if (x > 1) c *= 3; // 处理剩余的大素数因子return c;
}signed main() {prime(); // 预处理素数int n, sum = 0;cin >> n;vector<int> e(n + 1);for (int i = 1; i <= n; i++) {cin >> e[i];}for (int i = 1; i <= n; i++) {int x = e[i];int ii = sqrt(x);// 先判断是否为平方数(非平方数不可能是完美遗物)if (ii * ii != x) continue;// 计算因数个数int f = con(ii);// 判断因数个数是否为素数且不等于2if (a[f] == 0 && f > 2) {sum += x;}}cout << sum << endl;return 0;
}
http://www.lryc.cn/news/612568.html

相关文章:

  • 云端软件工程智能代理:任务委托与自动化实践全解
  • 【golang】基于redis zset实现并行流量控制(计数锁)
  • 【AI智能编程】Trae-IDE工具学习
  • javascript常用实例
  • Dart语言语法与技术重点
  • InfluxDB 集群部署与高可用方案(一)
  • 解决Node.js v12在Apple Silicon(M1/M2)上的安装问题
  • css怪异模式(Quirks Mode)和标准模式(Standards Mode)最明显的区别
  • Java零基础笔记13(Java编程核心:异常、泛型)
  • 数据结构 二叉树(1)二叉树简单了解
  • Python数据可视化:从基础到高级实战指南
  • Pytorch-07 如何快速把已经有的视觉模型权重扒拉过来为己所用
  • C语言的数组与字符串练习题1
  • VINS-Fusion+UWB辅助算法高精度实现
  • KNN算法:从原理到实战应用
  • 人工智能——深度学习——认识Tensor
  • k8s的存储之statefulset控制器
  • 数据结构(4)
  • 图解 Claude Code 子智能体 Sub-agent
  • Verilog 仿真问题:打拍失败
  • C语言高级编程技巧与最佳实践
  • 如何给小语种视频生成字幕?我的实测方法分享
  • docker-compose部署file browser
  • P1983 [NOIP 2013 普及组] 车站分级
  • Spring文件泄露与修复方案总结
  • Unity 调节 Rigidbody2D 响应速度的解决方案【资料】
  • 聚合链接网站源码部署教程
  • 【开源分享】can-utils:深入解析 Linux CAN 工具集
  • 面试经典150道之多数元素
  • nflsoi 8.6 题解