[NOIP2002 提高组] 均分纸牌

题目描述

有N堆纸牌,编号分别为 1,2,…,N。每堆上有若干张,但纸牌总数必为N的倍数。可以在任一堆上取若干张纸牌,然后移动。

移牌规则为:在编号为1堆上取的纸牌,只能移到编号为2的堆上;在编号为N的堆上取的纸牌,只能移到编号为N−1的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。

现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。

例如N=4,4堆纸牌数分别为:

①9②8③17④6

移动3次可达到目的:

从 ③ 取4张牌放到 ④ (9,8,13,10)-> 从 ③ 取33张牌放到 ②(9,11,10,10)-> 从 ② 取11张牌放到①(10,10,10,10)。

输入格式

两行

第一行为:NN(NN 堆纸牌,1≤N≤100)

第二行为:A1,A2,…,An(N堆纸牌,每堆纸牌初始数,1≤Ai≤100001≤Ai​≤10000)

输出格式

一行:即所有堆均达到相等时的最少移动次数。

输入数据 1

4
9 8 17 6

输出数据 1

3

根据题目描述,我们需要将所有堆的纸牌数量调整为相等,并且要求移动次数最少。通过分析可以发现,每个非目标值的堆都需要至少一次移动来调整其数量,因此最少移动次数等于需要调整的堆的数量减一(当相邻堆都需要调整时,可以合并移动)。

以下是解决该问题的 C++ 代码:

#include <iostream>
#include <vector>
using namespace std;
int main()
{int n;cin >> n;vector<int> cards(n);int sum = 0;for (int i = 0; i < n; i++) {cin >> cards[i];sum += cards[i];}int avg = sum / n;for (int i = 0; i < n; i++) {cards[i] -= avg;}vector<int> prefix(n);prefix[0] = cards[0];for (int i = 1; i < n; i++) {prefix[i] = prefix[i-1] + cards[i];}int count = 0;for (int i = 0; i < n; i++) {if (prefix[i] != 0) {count++;}}cout << count << endl;return 0;
}

代码说明:

  1. 输入处理:首先读取堆数n,然后读取每堆的纸牌数量并计算总和。
  2. 计算平均值:总和除以堆数得到每堆应有的纸牌数量。
  3. 调整数组:将每堆的纸牌数量转换为与平均值的差值。
  4. 前缀和数组:计算调整后数组的前缀和,前缀和中的每个元素表示从第一堆到当前堆的总差值。
  5. 统计非零元素:前缀和数组中非零元素的数量即为最少移动次数。

该算法的时间复杂度为 O (n),能够高效处理题目给定的数据范围。

让我们通过逐步拆解问题和代码逻辑,深入理解如何通过前缀和数组的非零元素数量确定最少移动次数。

一、问题本质分析

  1. 核心矛盾:每堆纸牌数与平均值的差异需要通过移动消除。
  2. 移动规则:每次移动只能影响相邻堆,且移动方向受限(如堆 1 只能移到堆 2)。
  3. 关键观察
    • 若某堆的纸牌数与平均值的差为d,则必须通过移动d张纸牌到相邻堆来平衡。
    • 每次移动可以消除一个累积的不平衡(即前缀和中的非零值)。

二、代码逻辑详解

1. 输入处理与平均值计算
int n;
cin >> n;
vector<int> cards(n);
int sum = 0;
for (int i = 0; i < n; i++) {cin >> cards[i];sum += cards[i];
}
int avg = sum / n;

  • 输入处理:读取堆数n和每堆的初始纸牌数。
  • 平均值计算:总和sum除以堆数n得到目标值avg。若纸牌总数不是n的倍数,题目保证输入合法,因此无需处理。

2. 调整数组(差值数组)
for (int i = 0; i < n; i++) {cards[i] -= avg;
}

  • 差值数组:将每堆的纸牌数转换为与平均值的差值。例如,若某堆初始有 9 张,平均值为 10,则差值为-1,表示需要移入 1 张纸牌。

3. 前缀和数组构造
vector<int> prefix(n);
prefix[0] = cards[0];
for (int i = 1; i < n; i++) {prefix[i] = prefix[i-1] + cards[i];
}

  • 前缀和的意义prefix[i]表示从第 1 堆到第i堆的总差值。例如,若前 3 堆的差值分别为-1, -2, 7,则prefix[2] = -1 + (-2) + 7 = 4,表示前 3 堆总共多出 4 张纸牌,需要后续堆来平衡。

4. 统计非零元素数量
int count = 0;
for (int i = 0; i < n; i++) {if (prefix[i] != 0) {count++;}
}
cout << count << endl;

  • 移动次数的来源:前缀和数组中的每个非零元素代表一个必须进行的移动步骤。例如:
    • prefix[i]为正,表示前i堆需要移出prefix[i]张纸牌;
    • 若为负,表示前i堆需要移入abs(prefix[i])张纸牌。
    • 每次移动可以消除一个非零的前缀和值,因此非零元素的数量即为最少移动次数。

三、数学证明与示例验证

1. 数学证明
  • 前缀和的性质
    由于所有堆的总差值为 0(总和为sum - n*avg = 0),前缀和数组的最后一个元素prefix[n-1]必为 0。
  • 移动次数的推导
    假设前缀和数组中有k个非零元素,每次移动可以消除一个非零值(例如,将prefix[i]的不平衡转移到下一堆),最终所有前缀和都变为 0,因此需要k次移动。

2. 示例分析(输入:4 9 8 17 6)
  • 步骤 1:计算平均值
    sum = 9+8+17+6 = 40avg = 40/4 = 10
  • 步骤 2:构造差值数组
    cards = [9-10, 8-10, 17-10, 6-10] = [-1, -2, 7, -4]
  • 步骤 3:计算前缀和数组
    prefix[0] = -1
    prefix[1] = -1 + (-2) = -3
    prefix[2] = -3 + 7 = 4
    prefix[3] = 4 + (-4) = 0
    非零元素为-1, -3, 4,共 3 个,对应移动次数 3。

3. 移动过程与前缀和的关系
  • 第一次移动:从堆 3 移 4 张到堆 4。
    差值数组变为[-1, -2, 3, 0],前缀和变为[-1, -3, 0, 0]。此时非零元素减少 1 个。
  • 第二次移动:从堆 3 移 3 张到堆 2。
    差值数组变为[-1, 1, 0, 0],前缀和变为[-1, 0, 0, 0]。非零元素再减少 1 个。
  • 第三次移动:从堆 2 移 1 张到堆 1。
    差值数组全为 0,前缀和全为 0。移动次数为 3。

四、时间复杂度分析

  • 输入处理:O(n)
  • 平均值计算:O(1)
  • 差值数组构造:O(n)
  • 前缀和数组构造:O(n)
  • 非零元素统计:O(n)
  • 总时间复杂度:O (n),可高效处理题目给定的n≤100的数据规模。

五、关键思想总结

  1. 差值数组:将问题转化为消除各堆与平均值的差异。
  2. 前缀和数组:将全局的移动需求转化为局部的累积不平衡。
  3. 贪心策略:每次移动消除一个累积的不平衡,非零前缀和的数量即为最少移动次数。

通过这种方法,我们无需模拟具体的移动过程,而是通过数学分析直接得出最优解,体现了算法设计中的抽象思维和问题转化能力。

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

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

相关文章

【音视频】WebRTC-Web 音视频采集与播放

一、打开摄像头 打开摄像头首先需要有一个html的video标签&#xff1a; id "local-video"&#xff0c;是为了后续的js脚本调用这个对象autoplay是设置打开后自动播放&#xff0c;playsinline则是为了兼容移动端 <video id "local-video" autoplay p…

数据治理平台如何选?深度解析国产化全栈方案与行业落地实践

“数据治理平台厂商有哪些&#xff1f;”国内主流厂商包括阿里云、华为、百分点科技等&#xff0c;各有所长。其中&#xff0c;百分点科技凭借在应急管理、智慧公安及央国企数字化领域的深度实践&#xff0c;打造了行业特色鲜明的数据治理解决方案。百分点科技的数据治理解决方…

限流算法详解:固定窗口、滑动窗口、令牌桶与漏桶算法全面对比

限流&#xff08;Rate Limiting&#xff09;是保障系统稳定性和服务质量的关键机制&#xff0c;尤其在高并发、突发流量、攻击防护等场景中至关重要。本文将详细介绍四种主流限流算法&#xff1a;固定窗口&#xff08;Fixed Window&#xff09;滑动窗口&#xff08;Sliding Win…

Sentinel 搭建应用层面与网关层面的流控保护

源码&#xff1a;妖精的尾巴/spring-cloud-alibaba Nacos 和 Sentinel Dashboard 我这里全是使用window 本地运行的&#xff0c;需要自行下载运行 服务层面&#xff1a; 当你在某个具体的服务上使用Sentinel时&#xff0c;更多的是关注该服务内部资源的保护。例如&#xff0c…

纯血鸿蒙 AudioRenderer+AudioCapturer+RingBuffer 实现麦克风采集+发声

总共两个类&#xff0c;放到代码里&#xff0c;就可以快速完成K歌的效果&#xff0c;但应用层这么做延迟是比较高的&#xff0c;只是做一个分享。 类代码 import { audio } from kit.AudioKit; import { BusinessError } from kit.BasicServicesKit; import { AudioBufferFlow,…

洛谷 P1601 A+B Problem(高精)普及-

题目描述 高精度加法&#xff0c;相当于 ab problem&#xff0c;不用考虑负数。 输入格式 分两行输入。a,b≤10500a,b \leq 10^{500}a,b≤10500。 输出格式 输出只有一行&#xff0c;代表 ababab 的值。 输入输出样例 #1 输入 #1 1 1输出 #1 2输入输出样例 #2 输入 #2 1001 909…

Matrix Theory study notes[6]

文章目录linear spacereferenceslinear space a basis of linear space VkV^kVk,which is x1,x2,...xkx_1,x_2,...x_kx1​,x2​,...xk​,can be called as a coordinate system.let vector v∈Vkv \in V^kv∈Vk and it can be linear expressed on this basis as va1x1a2x2...…

专线与专线之间的区别

下面我们从定义、技术特点、适用场景、优缺点等多个维度来详细对比&#xff1a;✅ 一、四种方案简要定义技术方案定义MPLS 专线运营商基于 MPLS 技术提供的私有虚拟网络&#xff0c;逻辑隔离、安全可靠VPN over Internet利用公网加密通道&#xff08;如IPSec&#xff09;构建虚…

Git工作流:团队协作的最佳实践

目录 一、什么是 Git 工作流&#xff1f;为什么需要它&#xff1f; 二、基础&#xff1a;Git 分支核心概念 三、主流 Git 工作流实战指南 1. 集中式工作流&#xff08;Centralized Workflow&#xff09;&#xff1a;适合小团队 / 新手 操作步骤&#xff1a; 优缺点&#…

算法竞赛阶段二-数据结构(35)数据结构单链表模拟实现

//链表--链式存储的线性表 //存信息和下一个节点位置&#xff0c;数据域和指针域合起来叫节点 //带头&#xff08;哨兵位&#xff09;下标为0 //单向&#xff0c;双向&#xff0c;循环链表 //实现 单 //俩足够大数组 // elem&#xff0c;数据域 // next &#xff0c;指针域…

《Computational principles and challenges in single-cell data integration》

1. 引言&#xff1a;单细胞数据整合的背景与重要性单细胞基因组学技术&#xff08;如scRNA-seq、scATAC-seq等&#xff09;近年来快速发展&#xff0c;能够以单细胞分辨率揭示细胞异质性和分子机制。然而&#xff0c;不同实验、样本和数据模态&#xff08;如RNA表达、DNA甲基化…

蔚来汽车携手通义灵码入选 2025 世界人工智能大会标杆案例

7月28日&#xff0c;在2025年世界人工智能大会上&#xff0c;通义灵码助力蔚来汽车研发效能升级成功入选2025年“人工智能”行业标杆案例荟萃。蔚来汽车已有近 1000 名工程师常态化使用通义灵码&#xff0c;AI 生成代码占比超 30%&#xff0c;尤其在蔚来“天探”AI自检系统的建…

Spring Boot中的this::语法糖详解

文章目录前言什么是方法引用&#xff08;Method Reference&#xff09;基本语法方法引用的四种类型1. 静态方法引用2. 实例方法引用&#xff08;特定对象&#xff09;3. 实例方法引用&#xff08;任意对象&#xff09;4. 构造器引用this::在Spring Boot中的应用场景1. Service层…

VitePress学习笔记

VitePress学习笔记VitePress学习搭建和运行编写内容mdvue配置站点配置配置searchsearch 提示词替换使用第三方主题自定义主题设置文档根目录国际化文档navsidebarsearch其他插件vitepress插件markdown-it插件项目开发原始需求和方案自动化流程权限限制VitePress学习 搭建和运行…

C#_创建自己的MyList列表

定义一个数据自己的列表MyList 使用上述描述列表的方式(数组) 列表内也要定义属于自己的方法 例如 Sort排序 Add添加 等等....思路┌─────────────────────────────────────────────────────────────────…

记录Linux下ping外网失败的问题

最近在RK3568上进行开发测试&#xff0c;需要测试一下网络环境&#xff0c;能否通过浏览器访问外部网络。测试情况如下&#xff1a; 1、ping内网、网关ip能ping通 2、ping外网ping不通 情况分析&#xff1a; 1、ping外网失败&#xff08;ping 8.8.8.8也ping不通&#xff0c;说…

Redis 键值对操作详解:Python 实现指南

一、环境准备 1. 安装依赖库 pip install redis2. 连接 Redis 数据库 import redis# 创建 Redis 客户端连接 r redis.Redis(hostlocalhost, # Redis 服务器地址port6379, # Redis 端口db0, # 数据库编号&#xff08;0~15&#xff09;passwordNone, …

制造业企业大文件传输的痛点有哪些?

在全球化与数字化的浪潮下&#xff0c;制造业企业的大文件传输需求日益凸显&#xff0c;然而诸多痛点也随之而来&#xff0c;严重制约着企业的高效运营与发展。复杂网络环境导致传输稳定性差制造业企业常涉及跨地域、跨国的业务合作与数据交流&#xff0c;网络环境复杂多变。在…

低速信号设计之 MDIO 篇

一、引言​ 在服务器的网络子系统中,MDIO(Management Data Input/Output)总线虽然传输速率相对较低,却扮演着极为关键的角色。它主要负责在 MAC(Media Access Control)层器件与 PHY(Physical Layer)层器件之间搭建起通信的桥梁,实现对 PHY 层器件的有效管理与状态监控…

AR技术赋能航空维修:精度与效率的飞跃

在航空工业领域&#xff0c;飞机维修与装配的精度要求越来越高。传统的维修方法依赖人工操作和经验判断&#xff0c;容易产生误差。随着增强现实&#xff08;AR www.teamhelper.cn &#xff09;技术的引入&#xff0c;航空维修迎来了革命性的变化。本文将探讨AR技术在航空维修中…