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

牛客周赛 Round 110

赛时成绩如下:

A. 小苯的数字染色

题目描述

猪猪王图拨号

又来考验他的猪猪部下了,这天他又找到了撤云猪猪

并给了他排成一排的 n 个白色数字。他希望将所有的数字都染红,但他仅允许撤云猪猪每次将相邻的两个白色数字染红,或将相邻的三个白色数字染红。(注意:操作可以进行任意次,但是染红的这 2 或 3 个数字必须都是白色的,而且相邻。)
但撤云猪猪实在太笨了,因此请你来帮帮他。你只需要判断,能否用任意次上述操作将所有的数字染红即可。

解题思路:每次可以选择染红2个/3个相邻的白色数字, n只要大于1都可以实现

#include<bits/stdc++.h>
using namespace std;
void solve(){int n;cin>>n;if(n!=1) cout<<"YES"<<'\n';else cout<<"NO"<<'\n';
}
int main(){int t=1;
//     cin>>t;while(t--){solve();}
}
B. 小苯的数组重排

题目描述

小苯有一个包含 n 个整数的数组,她想要重新排列数组的元素,使得相邻两个元素的加和之和最大。即最大化:
Sn=(a1​+a2​)+(a2​+a3​)+...+(an−1​+an​)。

你的任务就是帮助小苯找到最大的 S 值。

解题思路:

记sum=a1+a2+...+an

Sn=(a1+a2+...+an-1)+(a2+a3+...+an)=(sum-an)+(sum-a1)=2*sum-(a1+an)

因此要想保证Sn最大就要保证a1+an最小, 因此排列的时候找数组的最小和次小放到数组的开头和结尾即可

#include<bits/stdc++.h>
using namespace std;
using ll =long long;
void solve(){int n;cin>>n;vector<int> a(n);ll sum=0;for(int i=0;i<n;i++) { cin>>a[i]; sum+=a[i];}sort(a.begin(),a.end());cout<<sum*2-(a[0]+a[1])<<'\n';
}
int main(){int t;cin>>t;while(t--){solve();}
}
C. 小苯的麦克斯

题目描述

小苯在学习计算机的过程中,接触到了两个概念:MAX 和 MEX,对于一个序列来说,前者表示序列中的最大值,后者表示序列中未出现的最小非负整数。
这天,小红给了小苯一个长度为 n 的序列,她知道小苯分不清这些概念,因此特意提出了一个结合两个概念的题目:
她希望小苯从 a 中选择一个连续区间(不能只选一个数字)l,r (1≤l<r≤n),并最大化区间中所有的数字的 MAX−MEX,即最大值减去最小未出现非负整数的值。
现在请你帮小苯回答一下这个问题吧。

解题思路:从给定的数组中选取子区间,求MAX-MEX的最大值

结合题意观察示例1

1 2 3 4 5

为保证MAX-MEX最大,对于示例1, 这个子区间可以随便选, 只要包含数组中的最大数字即可

eg: [4,5] [3,4,5] [2,3,4,5] [1,2,3,4,5]

因为上面的子数组的mex都等于0

因此只要找一个包含最大数字的子数组即可,数组长度无所谓,选择len=2

子数组没有0,mex就为0,子数组没有1,mex就为1,

遍历的同时维护最大值max-mex即可

#include<bits/stdc++.h>
using namespace std;
void solve(){int n;cin>>n;vector<int> a(n);for(int i=0;i<n;i++) cin>>a[i];int ans=-1;for(int i=0;i+1<n;i++){int num_1=a[i],num_2=a[i+1];int max_num=max(num_1,num_2),mex=0;if(num_1==0||num_2==0){mex++;if(num_1==1||num_2==1){mex++;}}ans=max(ans,max_num-mex);}cout<<ans<<'\n';
}
int main(){int t;cin>>t;while(t--){solve();}
}
D. 小苯的平衡序列

题目描述

小苯有一个长度为 n 的整数序列 a1,a2,…,an​。他定义序列的"平衡度"为:
∑i=1n∣ai−median∣
其中 median 表示序列的中位数。如果序列长度是偶数,则中位数定义为较小的那个中间数(即下中位数)。
现在允许从序列中删除恰好一个元素,请计算删除哪个元素可以使剩下的序列的平衡度最小,并输出这个最小的平衡度。

解题思路:

把序列排序为 A[0..n−1],然后考虑删除排序后下标为 k 的元素。剩下的序列仍是有序的,长度为 n−1,它的“下中位数”(题中对偶数长度取较小的中间数)在剩下序列中的下标为m′=[(n-2)/2].floor,将m′映射回原排序数组的下标为

m=m′+(k≤m′?1:0),

因为如果被删元素在原来 m′(或更左)的位置,会把原下标 >k 的元素在剩下序列中的下标左移 1

已知中位数为 A[m],平衡度(删除 k 后)等于对所有 i≠k的 ∣A[i]−A[m]∣ 之和。利用前缀和可以 O(1) 地计算出左侧与右侧的和与个数(需要注意把被删元素从对应区间的和与计数中去掉)。对每个 k 计算候选值并取最小即可

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve() {int n; cin >> n;vector<int> a(n);for (int i = 0; i < n; i++) cin >> a[i];sort(a.begin(), a.end());vector<ll> pre_sum(n + 1);for (int i = 0; i < n; i++) pre_sum[i + 1] = pre_sum[i] + a[i];int m = (n - 2) / 2; ll ans = LLONG_MAX;for (int i = 0; i < n; i++) {int x = m + (i <= m ? 1 : 0);ll l_cnt = x - (i < x ? 1 : 0) , r_cnt = (n - x - 1) - (i > x ? 1 : 0);ll sum_l = pre_sum[x] - (i < x ? a[i] : 0);ll sum_r = (pre_sum[n] - pre_sum[x + 1]) - (i > x ? a[i] : 0);ll v = a[x] * l_cnt - sum_l + sum_r - a[x] * r_cnt;ans = min(ans, v);}cout << ans << '\n';
}
int main() {int t; cin >> t;while (t--) {solve();}
}
E. 小苯的数字变换

小苯在研究一种特殊的数字变换。对于一个正整数 x,定义一个数字的"根"为不断将其各位数字相加直到得到个位数。例如:
根 (38)=3+8=11→1+1=2
根 (999)=9+9+9=27→2+7=9
现在给定一个数字串 x,请你求出:所有 x 的连续子区间代表的十进制数字(去掉前导 0 后)的 "根" 之和。

解题思路:

P[i]=(s[0]+s[1]+⋯+s[i−1]) mod 9
举例:s="23"

P[0]=0

P[1]=(2)%9=2

P[2]=(2+3)%9=5

2. 子串模公式
任意子串 s[i..j-1] 的数位和模 9 = (P[j]−P[i]) mod 9
所以只要知道某个右端点 j 的 P[j],就能和所有左端点 i 的 P[i] 配对,得到所有子串 [i..j-1] 的模。

3. cnt[r] 是什么?
它表示:到目前为止,前缀模数等于 r 的前缀有多少个

比如 s="23",我们走到 j=2(cur=5):

之前的前缀有 P[0]=0, P[1]=2。

所以 cnt[0]=1, cnt[2]=1。

它们就是子串的潜在左端点。

4. 为什么要用 cnt?
因为我们要算 (P[j]−P[i]) mod 9

有 cnt[ri] 个前缀模等于 ri。

它们对应的子串模 = (cur - ri) mod 9。

所以一次性加 cnt[ri] 到 f[(cur-ri)%9]。

5. f 的作用
f[r] = 所有子串里,数位和模 9 等于 r 的子串个数。

r=1..8:数字根就是 r。

r=0:要拆分成“全零子串”和“非零但 %9==0 的子串”。

eg:
s = "23"

初始化:cnt[0]=1,f 全 0。

j=1,cur=P[1]=2
ri=0 → res=(2-0)%9=2 → f[2]+=cnt[0]=1

更新 cnt[2]++

现在 f[2]=1(子串 "2")。

j=2,cur=P[2]=5
ri=0 → res=(5-0)%9=5 → f[5]+=cnt[0]=1

ri=2 → res=(5-2)%9=3 → f[3]+=cnt[2]=1

更新 cnt[5]++

最后:

f[2]=1 ("2")

f[3]=1 ("23")

f[5]=1 ("3")

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve(){string a; cin >> a;int n = a.size();ll c = 0;for(int i=0;i<n;){if(a[i] != '0'){ i++; continue; }int j = i;while(j < n && a[j] == '0') j++;ll len = j - i;c += len * (len + 1) / 2;i = j;}vector<int> d(n+1, 0);for(int i=0;i<n;i++){int x = a[i]-'0';d[i+1] = (d[i] + x) % 9;}ll e[9] = {0}; ll f[9] = {0};e[d[0]] = 1;for(int i=1;i<=n;i++){int cur = d[i];for(int r=0;r<9;r++){int res = (cur - r) % 9;if(res < 0) res += 9;f[res] += e[r];}e[cur] += 1;}ll ans = 0;for(int r=1;r<=8;r++) ans += r * f[r];ll t = f[0];ll nz = t - c;if(nz > 0) ans+=9*nz;cout << ans << '\n';
}
int main(){int t;cin >> t;while(t--){solve();}return 0;
}
F. 小苯的序列合并

题目描述

给定长度为 nnn 的序列 a,你可以对 a 做如下操作任意次:
选择一个下标 i (1≦i<∣a∣),将 ai与 ai+1​ 合并起来,结果为 ai⊕ai+1(其中⊕ 表示按位异或运算符,∣a∣表示 a 当前的长度。)
所有操作结束后,小苯希望你最大化最终 a 中所有数字的按位与,即 AND值,请你算一下这个最大值是多少吧。

解题思路:

任意次操作ai和ai+1合并,最后得到的数组a再进行合并,输出合并最大值

合并等价与划分

结论题:一定可以划分成不超过两段区间

1. 直接整个区间进行 &

2. 每个区间的中间节点 ak

(a1 xor a2 xor...xor ak) & (ak+1 xor ... xor an)

然后前缀异或和即可

证明:

偶数最终变成2,奇数最终变成1

#include<bits/stdc++.h>
using namespace std;
void solve(){int n; cin >> n;vector<int> a(n); for(int i=0;i<n;i++) cin>>a[i];int ans = 0; for (auto& x : a) ans ^= x; for (int i = 1; i < n; i++) { a[i] ^= a[i - 1]; }for (int i = 0; i < n; i++) ans = max(ans, (a[n - 1] ^ a[i]) & a[i]);cout << ans << '\n'; 
}
int main(){int t;cin>>t;while(t--){solve();}
}

感谢大家的点赞和关注,你们的支持是我创作的动力!

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

相关文章:

  • AutoMQ x Lightstreamer: Kafka 金融数据实时分发新方案
  • Vulkan原理到底学什么
  • 第14讲 机器学习的数据结构
  • MATLAB的宽频带频谱感知算法仿真
  • Adobe Fresco下载教程Adobe Fresco 2025保姆级安装步骤(附安装包)
  • MQTT 服务质量 (QoS) 深度解析
  • MySQL EXPLAIN 中的七种 type 类型详解
  • NestJS认识
  • 6.MySQL索引的数据结构【面试题】
  • 【vLLM 最新版v0.10.2】docker运行openai服务与GGUF量化使用方式
  • 鸿蒙开发入门:ArkTS基础与实战
  • #C语言——刷题攻略:牛客编程入门训练(十三):一维数组(二),轻松拿捏!
  • 2.16Vue全家桶-Vuex状态管理
  • 【SSR】SSR 性能问题
  • 《UE教程》第二章第四回——父类蓝图
  • GORM库用法查漏补缺
  • C++11 移动语义与右值
  • FPGA学习笔记——图像处理之对比度调节(直方图均衡化)
  • 如何进行人脸识别
  • 计算机视觉笔试选择题:题组1
  • 第八篇:常量表达式:从const到constexpr的革命
  • RV1126 NO.30:RV1126多线程获取音频AI的PCM数据
  • 基于蚁群算法解决车辆路径问题(VRP)的MATLAB实现
  • C语言自学--C语⾔内存函数
  • 磁带记录仪:从磁带到数字的数据存储之旅
  • 【运维】Ubuntu上WebDAV挂载与自动同步完整指南
  • Ubuntu之旅-04 Docker
  • python(73) 引用.dll文件并调用函数
  • Chrome 学习小记5——demo:(动态壁纸基础)
  • 手写 Android Dex VMP 壳:自定义虚拟机 + 指令解释执行全流程