2026河南萌新联赛第六场(郑州大学)补题B、D、L、J、I

文章目录

题号 题目 难度
C ✅ 报数 easy
G✅ 找不同 easy
L✅ 神秘数字 medium easy
B✅ 果树 medium easy
D✅ 垂直电梯 medium easy
J✅ 空调 medium
F 虚狩武器 medium
I✅ 耳鸣 medium
H Clank! medium hard
E 演唱会 hard
M 你追我逃 hard
K 跳楼机 hard
A 强烈的以太波动 very hard

B题-果树

在开始B题之前 先来看一个Kadane卡登算法

专门用来求数组的最大子数组和

P1115 最大子段和 - 洛谷

假如是以当前元素x作为结尾的连续字段的最大和

x :舍弃前面所有子段,子段从当前x重新开始

前面的和是负数,带上只会拖累x,不如重新开始

sum+x:把x接到上一段子段后面,步步高上

举例子: 上一轮sum = -2,现在x = 3

  • sum+x = -2+3 = 1
  • max(3 , 1) → 选3 含义:前面‑2 这一段不要了,直接从 3 开启新子段。

上一轮sum=3x=-1

  • sum+x = 2
  • max(-1 , 2) →选2 含义:虽然 x 是负数,但接上前面总和依旧更大,继续延续子段。

sum每一轮都在更新,保存的一定是以当前位置结尾的最优连续和。

ans = max(sum, ans);

ans:记录全局历史上出现过最大的子段和

cpp 复制代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define ull unsigned long long
#define fi first
#define se second
#define PLL pair<ll, ll>
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
using namespace std;
const ll MAXN=100005;
const ll mod=1e9+7;
using namespace std;
ll n;
ll ans=-1e18;
int main()
{
	IOS
	cin>>n;
	ll sum=0;
	for(ll i=1;i<=n;i++)
	{
		ll x;
		cin>>x;
		sum=max(x,sum+x);
		ans=max(sum,ans);	
	}
	cout<<ans<<endl;
//	cout<<fixed<<setprecision(x)<< ;
	return 0;
}

B-果树_河南萌新联赛2026第(六)场:郑州大学

果树下标从 0 开始,只能摘偶数下标 (0,2,4...)苹果。 可以最多反转一次区间l,r。 反转之后元素位置改变;

只有区间长度是偶数,反转才会改变采摘得到的总数;

长度奇数反转完全没用,直接不用考虑

举例:区间 1 , 3 1,3 1,3长度 3。 原来位置 1 的元素,反转后跑到位置 3;1 是奇数,3 也是奇数。 原来位置 2 的元素,还留在位置 2;偶数依旧偶数。

  1. l 偶数,r 奇数:例 0,1, 2,3
  2. l 奇数,r 偶数:例 1,2, 3,4

差值:对这段字段的增益

只要是去看 奇数-偶数 去观察什么时候 累加最大 也就是在将差值记录下来后 最大的子段和

也就是说上述两种情况

cpp 复制代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define ull unsigned long long
#define fi first
#define se second
#define PLL pair<ll, ll>
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
using namespace std;
const ll MAXN=100005;
const ll mod=1e9+7;
using namespace std;
ll n;
ll a[MAXN];
ll sum[MAXN];
int main()
{
	IOS
	cin>>n;
	ll sum=0;
	vector<ll>v;//偶开头 奇结尾
	vector<ll>q;//奇开头 偶结尾
	for(ll i=0;i<n;i++)
	{
		cin>>a[i];
	}
	for(ll i=0;i<n;i+=2)
	{
		sum+=a[i];
	}
	for(ll i=0;i+1<n;i+=2)
	{
		v.push_back(a[i+1]-a[i]);
	}
	for(ll i=1;i+1<n;i+=2)
	{
		q.push_back(a[i]-a[i+1]);
	}
	ll sum1=0;
	ll ans1=0;
	ll sum2=0;
	ll ans2=0;
	for(ll i=0;i<v.size();i++)//寻找偶数开头的最大子段和
	{
		sum1=max(v[i],sum1+v[i]);
		ans1=max(ans1,sum1);
	}
	for(ll i=0;i<q.size();i++)//寻找奇数开头的最大子段和
	{
		sum2=max(q[i],sum2+q[i]);
		ans2=max(ans2,sum2);
	}
	cout<<sum+max(ans1,ans2)<<endl;

//	cout<<fixed<<setprecision(x)<< ;
	return 0;
}

D-垂直电梯

D-垂直电梯_河南萌新联赛2026第(六)场:郑州大学

  • i号电梯对应数字 s = i + 1 s=i+1 s=i+1;电梯停靠:s的所有因数、s的所有 ≤ n \le n ≤n的倍数。
  • 坐一次电梯 x → y x\to y x→y,花费: m + y − x m+y-x m+y−x。
  • 可以在同层无限换乘,起点a,终点b,求最小总费用。

本题一定有解,不存在 No Solution,永远最多坐 2 次电梯,借助 1 层中转

路径: c 0 = a → c 1 → c 2 ⋯ → c k = b c_0=a \to c_1 \to c_2 \dots \to c_k = b c0=a→c1→c2⋯→ck=b,共乘坐 k 次电梯

总费用: W = k ⋅ m + ( b − a ) \boldsymbol{W = k\cdot m + (b-a)} W=k⋅m+(b−a)

b − a b-a b−a是固定常数,最小化总费用等价于最小化电梯乘坐次数 k

最小乘坐次数 k m i n k_{min} kmin

1 层是所有正整数的因数,全部电梯都会停靠 1 层

  • 无法直达就中转: a → 1 → b a \to 1 \to b a→1→b两次电梯,k=2
  • k m i n k_{min} kmin只能取1或2

k m i n k_{min} kmin=1(直达)

总费用: W = m + ( b − a ) \boldsymbol{W =m+ (b-a)} W=m+(b−a)

满足任意一个条件,就存在电梯同时停靠a,b

  1. gcd(a,b)>=2
    • s=gcd(a,b),电梯编号s-1;ab均为s的倍数,可直达
  2. lcm(a,b)<=n
    • s=lcm(a,b),电梯编号s-1;ab均为s的因数,可直达

k m i n k_{min} kmin=2(中转)

上述两个条件均不成立走1层中转

总费用: W = 2 ⋅ m + ( b − a ) \boldsymbol{W = 2\cdot m + (b-a)} W=2⋅m+(b−a)


cpp 复制代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define ull unsigned long long
#define fi first
#define se second
#define PLL pair<string, ll>
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
using namespace std;
const ll MAXN=1005;
const ll mod=1e9+7;
using namespace std;
ll T;
ll n,m,a,b;
int main()
{
	IOS
	cin>>T;
	ll ans=0;
	while(T--)
	{
	cin>>n>>m>>a>>b;
	if(__gcd(a,b)>1||a*b<=n)
	{
		ans=0;
	}	
	else
	{
		ans=m;
	}
	cout<<m-a+b+ans<<endl;
	}
	
//	cout<<fixed<<setprecision(x)<< ;
	return 0;
}

L-神秘数字

L-神秘数字_河南萌新联赛2026第(六)场:郑州大学

神秘数字 x: 1 ≤ x ≤ n 1\le x \le n 1≤x≤n,我们不知道它。

我们要造出 m 个数字集合。 把全部 m 个集合拿给对方。 对方对每一个集合回答:这个 x 在不在这个集合里(是 / 否)

我们拿到 m 个 "是 / 否" 答案之后,必须唯一确定 x 是几 。 求:m 最小是多少,并且输出这 m 个集合。

本质是二进制

m :二进制位数,也就是 ⌈ log ⁡ 2 n ⌉ \lceil \log_2 n\rceil ⌈log2n⌉。

cpp 复制代码
while((1ll<<m)<n)
	{
		m++;
	}

每一个集合对应二进制的一位。 回答 "在集合"= 这一位是 1;回答 "不在集合"= 这一位是 0

举例:5

  • 第 1 个集合(最低位,第 0 位):存放二进制第 0 位等于 1 的数:{1,3,5}
  • 第 2 个集合(第 1 位):存放二进制第 1 位等于 1 的数:{2,3}
  • 第 3 个集合(第 2 位):存放二进制第 2 位等于 1 的数:{4,5}

不管 x 是 1~5 中哪一个,三次回答的 01 序列就是 x 的二进制,直接还原数字

cpp 复制代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define ull unsigned long long
#define fi first
#define se second
#define PLL pair<string, ll>
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
using namespace std;
const ll MAXN=1005;
const ll mod=1e9+7;
using namespace std;
ll n;
int main()
{
	IOS
	cin>>n;
	ll m=0;
	while((1ll<<m)<n)
	{
		m++;
	}
	cout<<m<<endl;
	for(ll i=0;i<m;i++)
	{
		vector<ll>v;
		for(ll j=1;j<=n;j++)
		{
			if(j>>i&1)
			{
				v.push_back(j);
			}
		}
		cout<<v.size();
		for(auto x:v)
		{
			cout<<' '<<x;
		}
		cout<<endl;
		
	}
	
//	cout<<fixed<<setprecision(x)<< ;
	return 0;
}

J-空调

J-空调_河南萌新联赛2026第(六)场:郑州大学

  • x = ∣ t − 26 ∣ + m − 1 x = |t-26| + m-1 x=∣t−26∣+m−1:到达目标状态最少总按键次数

  • r e s t = n − x rest = n-x rest=n−x:多余、需要被消耗掉的按键次数

  • n<x总按键数目 也是不够的直接输出Lie

  • n>=x,下列四个条件满足一个即为Maybe否则Lie

条件编号 条件表达式 说明
条件 1 rest % 2 =0 剩余步数为偶数。到达目标后反复+来回抵消,消耗偶数步,状态不变。
条件 2 n>=(R−26)+(R−t)+(m−1) 步数足够跑到上边界R。跑到 R 之后反复按+无效,消耗多余步数。
条件 3 n>=(26−L)+(t−L)+(m−1) 步数足够跑到下边界L。跑到 L 之后反复按无效,消耗多余步数。
条件 4 rest%2=1 &&K%2=1 && n>=x+K 剩余步数奇数,K为奇数,总步数足够多。完整循环一轮模式K次,模式复原,消耗奇数步,把rest转为偶数。
cpp 复制代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define ull unsigned long long
#define fi first
#define se second
#define PLL pair<string, ll>
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
using namespace std;
const ll MAXN=1005;
const ll mod=1e9+7;
using namespace std;
ll T;
ll L,R,k,n,t,m;
int main()
{
	IOS
	cin>>T;
	while(T--)
	{
		cin>>L>>R>>k>>n>>t>>m;
		ll x=abs(t-26)+m-1;
		if(n<x)
		{
			cout<<"Lie";
		}
		else if((n-x)%2==0)
		{
			cout<<"Maybe";
		}
		else if(n>R-26+R-t+m-1||n>26-L+t-L+m-1)
		{
			cout<<"Maybe";
		}
		else if(k%2==1&&(n-x)%2==1&&n>=x+k)
		{
			cout<<"Maybe";
		}
		else
		{
			cout<<"Lie";
		}
		cout<<endl;
	}
	
//	cout<<fixed<<setprecision(x)<< ;
	return 0;
}

I-耳鸣

I-耳鸣_河南萌新联赛2026第(六)场:郑州大学

刚拿到题,第一想法肯定是暴力思路(虽然直观,但是太慢)

对每一个圆,二重循环遍历圆内每一个格子,标记vis[i][j]=1,最后统计 1 的个数 总复杂度爆炸,直接 TLE。

用差分优化 可以将复杂度降到O(1)

差分优化 差分维护行区间

将圆按行处理

  • 对于圆心(x,y)枚举圆每一行号j(纵向范围:x-a<=j<=x+a,并且限制在网格1~n,保证不越界)

  • 当前行距离圆心纵向距离:dx=|j-x|

    由 dx2+dy2<=a2 可得 dy2<=a2-dx2 dymax=sqrt( a2-dx2 )

    所以 圆覆盖 列区间 \[y-dy~max~,y+dy~max~\], 再裁剪到网格[1,m],得到[l1,r1];

    对于本行,区间[l1,r1]全部+1

cpp 复制代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define ull unsigned long long
#define fi first
#define se second
#define PLL pair<string, ll>
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
using namespace std;
const ll MAXN=1005;
const ll mod=1e9+7;
using namespace std;
ll n,m,a,q;

int main()
{
	IOS
	cin>>n>>m>>a>>q;
	vector<ll>diff((n+2)*(m+2),0);
	//二维网格压成一维差分数组
	for(ll i=1;i<=q;i++)
	{
		ll x,y;
		cin>>x>>y;
		//枚举圆纵向覆盖的每一行j
		for(ll j=max(1ll,x-a);j<=min(n,x+a);j++)
		{
			ll s=a*a-(x-j)*(x-j);
			ll l=(ll)(sqrt(s));
			while((l+1)*(l+1)<=s)//修正sqrt向下取整误差,防止l偏小
			{
				l++;
			}
			ll l1=max(1ll,y-l),r1=min(m,y+l);
			diff[(j-1)*m+l1]++;
			diff[(j-1)*m+r1+1]--;
		}
	}
	ll ans=0;
	ll k=0;
	for(ll i=1;i<=n*m;i++)
	{
		k+=diff[i];
		if(k!=0)
		{
			ans++;
		}
	}
	cout<<ans<<endl;
	
//	cout<<fixed<<setprecision(x)<< ;
	return 0;
}
相关推荐
朝发如雪1 小时前
快速掌握Linux(2)(时间相关函数)(文件IO)
linux·python·算法
Forever Nore1 小时前
LeetCode 16 最接近的三数之和 - 双指针逼近
算法·leetcode·职场和发展
心仪久了会沦陷1 小时前
数据结构入门系列——顺序表详解:概念、分类与动态实现
c语言·数据结构·经验分享·笔记·开源
smj2302_796826521 小时前
解决leetcode第4033题有效K个不同元素子数组I
数据结构·python·算法·leetcode
witton1 小时前
xmake中将proto文件生成C/C++文件然后再编译链接进项目
c语言·c++·mingw·protobuf·xmake·protobuf-c·protoc-gen-c
牛油果子哥q1 小时前
C++异常处理万字详解:try-throw-catch机制、栈展开、标准异常体系、自定义异常、工程规范、内存泄漏避坑
开发语言·jvm·c++
艾莉丝努力练剑1 小时前
【AI大模型接入SDK】C++日志体系与spdlog封装的理论部分
开发语言·c++·ide·人工智能·学习·面试·trae
学linux的QQ蛋2 小时前
Linux 文件 IO:系统调用 open/read/write 完整总结
linux·运维·算法
rannn_1112 小时前
【力扣hot100】回溯专题|全排列、子集、字母组合、组合总和、括号生成、单词搜索、分割回文串、N皇后
java·算法·leetcode·回溯