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

河南萌新联赛2025第(四)场:河南大学

链接:(8条未读私信) 河南萌新联赛2025第(四)场:河南大学_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ

难度:

  • 签到:A,C,G,J

  • 简单:B,D,L

目录

A. 完美序列

思路分析:

实现代码:

C.  合并石子

思路分析:

实现代码:

G. 封闭运算

思路分析:

实现代码:

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

思路分析:

实现代码:

B.  0!!!!!

思路分析:

实现代码:

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

思路分析:

实现代码:


A. 完美序列

思路分析:

  1. 统计数字出现次数​​:使用一个数组 cnt统计每个数字 x在序列 a中出现的次数 cnt[x]。

  2. ​​计算所有可能的和 s的覆盖次数​​:

    • 遍历所有可能的数对 (i,j)(其中 i≤j),计算每个和 s=i+j的覆盖次数 sum[s]。

      • 如果 i=j,则最多可以组成 cnt[i]/2个数对(每个数对需要两个相同的数字)。

      • 如果 i  !=j,则最多可以组成 min(cnt[i],cnt[j])个数对(取较小的那个数字的出现次数)。

    • 将所有这些数对的贡献累加到 sum[s]中。

  3. ​​找到最大的覆盖次数​​:

    • 遍历所有可能的和 s(从 2到 10000),找到最大的 sum[s]。

    • 完美序列 b的最大长度为 2×max(sum),因为每个数对可以贡献 2 个元素。

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
const int N=2e5+2;
int a[N],sum[N];
void slove(){
int n,x;
cin>>n;
for(int i=1;i<=n;i++)
{cin>>x;a[x]++;
}for(int i=1;i<=5000;i++)
{for(int j=i;j<=5000;j++){if(i==j)sum[i+j]+=a[i]/2;elsesum[i+j]+=min(a[i],a[j]);}
}
int  t=1;
for(int i=1;i<=10010;i++)
{t=max(t,sum[i]);
}
cout<<2*t;}
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int _=1;//cin>>_;while(_--)slove();return 0;
}

C.  合并石子

思路分析:


根据样例可以知道合并石子必须得从两边向中间移动石子,使用左右指针l和r分别指向数组的首尾。每次选择当前石子数量较少的一端进行合并,这样可以尽量减少移动次数。每次移动a[i]个石子,每次最多移动k个,因此需要⌈a[i]/k⌉次(记得向上取整数)操作(即体力消耗)。

实现代码:
 

#include<bits/stdc++.h>
using namespace std;
#define int long long  
#define endl '\n'      
#define pii pair<int,int>  
#define fi first       
#define se second      
const int N=2e5+4;    
int a[N];          void slove(){int n,k;          cin>>n>>k;for(int i=1;i<=n;i++) {cin>>a[i];  }int l=1,r=n,ans=0; // 初始化双指针l和r,ans记录体力消耗while(l<r) {       // 当左右指针未相遇时循环if(a[l]<a[r]) { // 左侧石子较少a[l+1]+=a[l]; // 将左侧石子全部移到右侧相邻堆ans+=(a[l]+k-1)/k; // 计算移动所需体力(向上取整)l++;        // 左指针右移}else {          // 右侧石子较少或相等a[r-1]+=a[r]; // 将右侧石子全部移到左侧相邻堆ans+=(a[r]+k-1)/k; // 计算移动所需体力r--;        // 右指针左移}}cout<<ans;          // 输出最小体力消耗
}signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int _=1;//cin>>_;while(_--)slove();return 0;
}

G. 封闭运算

思路分析:


题目中说,若对于数组中任意的 i , j(1≤i≤j≤n)都存在一个 k,使得 a[ i ]∣a [ j ]=a[k]​ (其中 ∣ 表示按位或),则称该数组对于按位或运算是封闭的。所以我们只要找到存不存在就可以了。先把所有的数都存到一个哈希数组里面,方便查找,然后用两个for循环进行位运算,然后再数组里面找看存不存在运算后的数,只要有一个不存在,就不是封闭运算。

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
const int N=101;
int a[N];
unordered_set<int> mp;
void slove(){
int n;
cin>>n;for(int i=0;i<n;i++)
{cin>>a[i];mp.insert(a[i]);
} for(int i=0;i<n;i++){for(int j=i;j<n;j++){int t=a[i]|a[j];if(mp.find(t)==mp.end()){cout<<"NO"<<endl;return ;}
}}
cout<<"YES"<<endl;}
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int _=1;//cin>>_;while(_--)slove();return 0;
}

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

思路分析:


【字典序】:从两个数组的第一个元素开始逐个比较,直到找到第一个不同的元素,较大元素所在的数组的字典序较大。如果比较到其中一个数组的结尾时依旧全部相同,则较短的数组字典序更小。

读取牌的数量 n和第一张牌的威力 a[1]。如果 n == 1,直接输出这张牌的威力,因为无法进行交易。

​寻找最大威力牌​​:初始化 mx和 p为0。遍历第2张到第n张牌,更新 mx和 p为当前最大值及其位置。

如果有多个最大值,选择最后面的那个(通过 >=实现)。

​​全零情况处理​​:如果 mx == 0,说明所有牌的威力都是0,无法通过交易增加字典序,直接输出所有牌。将第一张牌的威力 a[1]加上最大威力牌 a[p]的威力。将 a[p]标记为-1(表示删除)。

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
const int N=2e5+2;
int a[N];
void slove(){int n;cin>>n;cin>>a[1];if(n==1)//只有一张牌 {cout<<1<<endl<<a[1]<<endl;return ;}int mx=0,p=0;for(int i=2;i<=n;i++){cin>>a[i];if(a[i]>=mx)//当有多个最大的数字,选最后面的 {mx=a[i];p=i;}}if(a[p]==0)//输入的全是0的情况 {cout<<n<<endl;for(int i=1;i<=n;i++){cout<<a[i]<<' ';}return ;}a[1]+=a[p];a[p]=-1;cout<<n-1<<endl;for(int i=1;i<=n;i++){if(a[i]!=-1)cout<<a[i]<<' ';}
}
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int _=1;//cin>>_;while(_--)slove();return 0;
}

B.  0!!!!!

思路分析:


这道题目要求计算区间[L, R]内所有整数的因数乘积末尾零的个数。关键在于理解末尾零的产生原理:每个零都由一对2和5的质因数相乘产生(10=2×5)。因此,我们需要统计所有因数乘积中2和5的质因数总数,并取两者的较小值作为答案。代码实现采用数论分块技术进行高效计算:首先定义calculate函数,通过遍历x的幂次(x, x², x³...)并使用数论分块统计区间内能被x的幂次整除的数的个数;然后在solve函数中分别计算区间内2和5的幂次总数,通过区间减法得到[L,R]范围内的统计结果,最终输出两者的最小值。

实现代码:

#include <iostream>
#include <algorithm> using namespace std;// 计算在[1, lim]范围内能被x的幂次整除的数的个数
long long calculate(long long x, long long lim) {long long num = 0; // 计数器,记录满足条件的数的个数// 遍历x的所有幂次:x, x^2, x^3,...直到超过limfor(long long i = x; i <= lim; i *= x) {long long n = lim / i; // 计算能被i整除的数的最大商// 使用数论分块优化计算for(long long l = 1; l <= n; ) {// 计算当前块的右边界long long r = n / (n / l); // 当前块内的数的个数乘以它们的商值num += (r - l + 1) * (n / l);// 移动到下一个块l = r + 1;}}return num;
}void solve() {long long L, R;cin >> L >> R; // 计算区间内能被2的幂次整除的数的个数long long a = calculate(2, R) - calculate(2, L - 1);// 计算区间内能被5的幂次整除的数的个数long long b = calculate(5, R) - calculate(5, L - 1);// 输出两者中的较小值cout << min(a, b) << '\n';
}int main() {ios::sync_with_stdio(false); cin.tie(nullptr); int T = 1;// cin >> T; while(T--) {solve(); }return 0;
}

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

思路分析:

这道题目要求我们找出所有满足"完美遗物"条件的数字并求和。完美遗物的定义是:该数字的因数个数是一个质数且不等于2。通过分析可以发现,只有特定形式的数字才能满足这个条件。

观察到:完全平方数的因数个数是奇数,非完全平方数的因数个数是偶数,

因数个数为质数的完全平方数必须满足:该数可以表示为某个素数的偶数次幂(即p^(2m)),且2m+1是质数。

具体步骤:1.使用欧拉筛法预处理所有素数(标记在v数组中)

2. 预处理满足条件的数:遍历所有素数p,计算p的平方及更高次幂,检查幂次+1是否为质数,如果是,则标记该数的平方根(存储在vis数组中)。

3. 处理输入:对每个输入的数字,检查它是否是完全平方数,如果是,检查其平方根是否被标记为满足条件,累加所有满足条件的数字。

实现代码:
 

#include<bits/stdc++.h>
using namespace std;
#define int long long  
#define endl '\n'    
#define pii pair<int,int> 
#define fi first     
#define se second      
const int N=1e6+2;     
const int M=1e12;      int a[N], prime[N];    // a存储输入数字,prime存储素数
bool v[N], vis[N];     // v标记是否为合数,vis标记满足条件的数
int ans=0;             // 存储最终结果
int n, m, k;           // n是输入数字个数,k是素数个数// 欧拉筛法求素数
void oula() {v[1] = 1;  // 1不是素数for(int i=2; i<=N; i++) {if(!v[i]) prime[++k] = i;  // i是素数,存入prime数组for(int j=1; j<=k && i*prime[j]<=N; j++) {v[i*prime[j]] = 1;     // 标记合数if(i%prime[j]==0) break; // 关键优化:每个数只被最小素因子标记}}
}// 预处理满足条件的数
void pre() {for(int i=1; i<=k; i++) {  // 遍历所有素数int p = prime[i]*prime[i];  // 计算素数的平方for(int j=2; ; j++) {      // 计算更高次幂if(p > M) break;        // 超过最大值则终止if(j+1<N && !v[j+1]) { // 如果j+1是素数int t = sqrtl(p);   // 计算平方根if(t < N) vis[t] = 1; // 标记满足条件的数}p *= prime[i];          // 计算下一个幂次}}
}void slove() {cin >> n;for(int i=1; i<=n; i++) {cin >> a[i];}oula();  // 筛素数pre();   // 预处理满足条件的数for(int i=1; i<=n; i++) {int t = sqrtl(a[i]);  // 计算平方根if(t*t == a[i] && vis[t]) {  // 如果是完全平方数且满足条件ans += a[i];             // 累加到结果}}cout << ans;  
}signed main() {ios::sync_with_stdio(0);  cin.tie(0); cout.tie(0);  int _=1;//cin >> _; while(_--) {slove();  }return 0;
}

http://www.dtcms.com/a/319951.html

相关文章:

  • Taro 扩展 API 深度解析与实战指南
  • 考研复习-计算机组成原理-第三章-存储系统
  • 广州工艺品摆件三维扫描逆向建模抄数设计-中科米堆CASAIM
  • [三数之和]
  • [安卓按键精灵开发工具]本地数据库的初步学习
  • Day116 若依融合mqtt
  • Minio 分布式集群安装配置
  • 28 HTB Forest 机器 - 容易 (1)
  • (附源码)基于Web的物流信息管理系统
  • 解锁webpack核心技能(二):配置文件和devtool配置指南
  • 机器学习在量化中的应用:如何从逻辑回归到XGBoost实现高效预测?
  • 将Excel数据导入SQL Server数据库,并更新源表数据
  • 河南萌新联赛2025第(四)场:河南大学(补题)
  • 北京JAVA基础面试30天打卡04
  • 一文入门 matplotlib:从基础图表到数据可视化初体验
  • git branch -a无法查看最新的分支
  • CNB私有化部署Dify(零成本)教程
  • 操作系统1.4:操作系统的体系结构
  • ollama 运行gpt-oss 系列教程
  • Numpy科学计算与数据分析:Numpy数组创建与应用入门
  • DevOps简单教程应用
  • ⭐CVPR2025 RoboBrain:机器人操作的统一大脑模型[特殊字符]
  • Redis(八):Redis高并发高可用(哨兵Sentinel)
  • 上海一家机器人IPO核心零部件依赖外购, 募投计划频繁修改引疑
  • QDataStream入门
  • Redis实战(8) -- 分布式锁Redission底层机制
  • 如何解决用阿里云效流水线持续集成部署Nuxt静态应用时流程卡住,进行不下去的问题
  • 基于 MATLAB 的 QPSK 调制、解调、通过高斯信道的误码率计算,并绘制误码率图和眼图、星座图
  • 火山引擎接入豆包AI(纯前端调用api的方式)
  • Java 大视界 -- Java 大数据在智能教育在线课程互动优化与学习体验提升中的应用(386)