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

UVa 11166 Power Signs

题目描述

给定一个正整数n nn,它的二进制表示为不含前导零的二进制字符串。我们需要将n nn表示为带符号的二进制表示(signed binary representation \texttt{signed binary representation}signed binary representation),即:

n = ∑ i = 0 k a i × 2 i n = \sum_{i=0}^{k} a_i \times 2^in=i=0kai×2i

其中a i ∈ { − 1 , 0 , 1 } a_i \in \{-1, 0, 1\}ai{1,0,1}

在二进制表示中,每一位a i a_iai只能是0 001 11,因此表示是唯一的。但是在带符号的二进制表示中,每一位可以是− 1 -110 001 11,因此表示不唯一。题目要求我们找到一种带符号的二进制表示,使得其中非零数字(即+ 1 +1+1− 1 -11)的个数最少。如果存在多种最优解,则输出其中字典序最小的一个(按照ASCII \texttt{ASCII}ASCII码顺序比较,其中字符的顺序为'+' < '-' < '0')。

输入包含多个测试用例(最多25 2525个),每个测试用例一行,是一个正整数n < 2 50000 n < 2^{50000}n<250000的二进制表示(不含前导零)。输入以n = 0 n = 0n=0结束,该行不需处理。

对于每个测试用例,输出一行,给出满足条件的带符号二进制表示,用字符'+'表示+ 1 +1+1'-'表示− 1 -11'0'表示0 00,且不含前导零。

题目分析

本题的关键在于理解如何通过带符号的二进制表示来减少非零数字的个数。观察普通的二进制表示,连续的1 11串可以通过进位和借位的方式,转换为更少的非零数字。

例如,二进制数7 77的普通表示是111 111111(即4 + 2 + 1 4+2+14+2+1),其中有3 33个非零数字。但我们可以将其表示为100 − 100-100(即8 − 1 8-181),这样只有2 22个非零数字(+ 1 +1+1− 1 -11)。更一般地,连续的k kk1 11可以表示为:

11 … 1 ⏟ k 个 = 2 k − 1 = 2 k − 2 0 \underbrace{1 1 \dots 1}_{k \text{个}} = 2^k - 1 = 2^k - 2^0k111=2k1=2k20

即一个+ 1 +1+1在高位,k − 1 k-1k10 00在中间,一个− 1 -11在最低位。这样就将k kk个非零数字减少到了2 22个。

然而,这还不是最优的。因为当我们进行这样的转换时,会产生一个进位(即将连续1 11串前面的0 00变为1 11)。这个进位可能与更高位的1 11形成新的、更长的连续1 11串,从而可以进一步优化,减少更多的非零数字。

解题思路

基于以上分析,我们可以设计一个贪心算法,从二进制表示的最低位向最高位扫描,处理连续的1 11串。

算法步骤

  1. 初始化:在二进制字符串前添加一个字符'0'作为哨兵,用于处理可能的最高位进位。

  2. 从低位向高位扫描

    • 对于每个位置i ii(从最低位到最高位),如果当前字符是'1',则向前(向高位方向)寻找连续'1'的起始位置j jj(即s [ j ] = ′ 0 ′ s[j] = '0's[j]=0s [ j + 1.. i ] s[j+1..i]s[j+1..i]都是'1')。
    • 计算连续1 11的长度l e n = i − j len = i - jlen=ij
    • 如果l e n ≥ 2 len \ge 2len2,则进行转换:
      • s [ i ] s[i]s[i]改为'-'(表示− 1 -11)。
      • s [ j + 1.. i − 1 ] s[j+1..i-1]s[j+1..i1]改为'0'
      • s [ j ] s[j]s[j]改为'1'(进位)。
      • 注意:这里进位设为'1'而不是'+',因为它可能与更高位的'1'构成更长的连续1 11串,从而在后续扫描中被进一步优化。
    • 特殊情况:如果l e n = 2 len = 2len=2j = 0 j = 0j=0(即连续两个1 11在最高位),则直接将这两个位置设为'+',不进行转换(因为转换后最高位会变成'-',可能不是字典序最小)。
    • 如果l e n = 1 len = 1len=1(单个1 11),则直接将该位置设为'+'
  3. 处理最高位进位:扫描结束后,如果哨兵位s [ 0 ] s[0]s[0]变成了'1',则将其改为'+'

  4. 输出结果:如果s [ 0 ] = ′ 0 ′ s[0] = '0's[0]=0,则从s [ 1 ] s[1]s[1]开始输出;否则从s [ 0 ] s[0]s[0]开始输出。这样可以确保没有前导零。

算法正确性说明

该算法是贪心的,从最低位开始,每次遇到连续长度≥ 2 \ge 221 11串就进行转换。这样做的正确性基于以下观察:

  • 最优子结构:一个数的最优带符号二进制表示,其最低位的决策不会影响更高位的最优性(因为转换只产生向高位的进位,不影响已经处理过的低位)。
  • 贪心选择性质:对于连续的k kk1 11,立即进行转换(变为2 k − 1 2^k - 12k1)总是比保持原样更优或至少不差(当k ≥ 3 k \ge 3k3时严格更优,k = 2 k = 2k=2时需要特殊处理字典序)。
  • 字典序最小:由于我们从低位向高位处理,且在高位尽量保持'+'(而不是'-'),最终得到的表示在非零数字最少的前提下是字典序最小的。

时间复杂度

扫描整个字符串一次,每次处理连续1 11串时可能会修改多个字符,但每个字符最多被修改一次(从'1'改为'0''-'),因此总时间复杂度为O ( n ) O(n)O(n),其中n nn是二进制字符串的长度。由于n ≤ 50000 n \le 50000n50000,算法完全可行。

空间复杂度

只需要存储输入字符串和一些辅助变量,因此空间复杂度为O ( n ) O(n)O(n)

代码实现

// Power Signs// UVa ID: 11166// Verdict: Accepted// Submission Date: 2025-12-20// UVa Run Time: 0.000s//// 版权所有(C)2025,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;constintMAXN=50010;intmain(){chars[MAXN];while(scanf("%s",s+1)==1&&s[1]!='0'){s[0]='0';intn=strlen(s+1);// 从低位向高位扫描(i从n到1)for(inti=n;i>0;i--){if(s[i]=='1'){intj=i-1;// 向前寻找连续1的起始位置while(s[j]=='1')j--;// 检查连续1的长度// 连续1的长度≥2if(i-j>=2){// 特殊情况:连续2个1且在最高位(j==0)if(i-j==2&&j==0)s[i]=s[i-1]='+';else{// 一般情况:转换连续1// 最后一个1变成-1s[i]='-';// 中间的1变成0for(intk=i-1;k>j;k--)s[k]='0';// 进位(前面的0变成1),不变为+,因为有可能与前面的1构成更长的连续1串,// 从而可以得到非0数字更少的表示,从而可能会更优s[j]='1';}}elses[i]='+';// 单个1,直接变成+}}// 处理可能的最高位进位if(s[0]=='1')s[0]='+';// 输出结果if(s[0]=='0')printf("%s\n",s+1);elseprintf("%s\n",s);}return0;}

示例分析

样例输入

10000 1111 10111 0

样例输出

+0000 +000- ++00-

解释

  1. 10000 1000010000(二进制16 1616):

    • 没有连续1 11,直接转换为+0000
  2. 1111 11111111(二进制15 1515):

    • 从低位扫描,连续4 441 11,转换为1000 − 1000-1000,即+000-
  3. 10111 1011110111(二进制23 2323):

    • 首先处理低三位111 111111,转换为100 − 100-100,同时进位使前面变为1 11,得到1100 − 1100-1100
    • 然后处理新的连续两个1 11(在第二位和第三位),但由于它们在最高位且长度为2 22,不转换,直接设为++,最终得到++00-

总结

本题是一道典型的贪心算法题目,关键在于发现通过进位可以将连续的1 11串转换为更少的非零数字,并且这种转换可以连锁进行,从而得到全局最优解。算法的时间复杂度和空间复杂度都是线性的,适合处理大规模的输入数据。

http://www.cnnetsun.cn/news/167593.html

相关文章:

  • AI对打工人的三个影响
  • 小程序/APP接入分账系统:4大核心注意事项,避开合规与技术坑
  • 靠谱的厦门考研公司哪个好
  • 二叉搜索树的最近公共祖先:别再蛮力了,用规则思维找“血缘关系”
  • 推荐6个AI论文网站,提供降重与自然改写功能避免标红
  • 智能学术支持:6个AI论文平台解析,自动润色让内容更专业
  • 从手动测试到自动化测试的转型之路:策略、挑战与未来
  • 大数据工程师必看:批处理性能优化的10个黄金法则
  • 2026年AI全面爆发!AI原生、物理AI、多模态与世界模型的革命性变革
  • 【扣子Coze教程】文案一键仿写+飞书自动发布
  • 提示词工程精华总结:掌握ICIO框架与五大核心要素,AI应用效率翻倍,建议收藏!
  • 还在手动选品?RPA+AI生成希音爆款推荐,效率提升100倍![特殊字符]
  • 8个AI论文工具,自考学生轻松搞定毕业论文!
  • 8个降AI率工具推荐,继续教育学生必备
  • CTFer常见高频工具清单
  • 痞子衡嵌入式:16MB以上NOR Flash地址模式切换会造成软复位后i.MXRT无法正常启动
  • 爬山算法:无需微积分的机器学习之旅
  • 【Ctfer训练计划】——命令执行的解题技巧(持续更新中)
  • CTF wed安全(攻防世界)练习题
  • CTF进阶解题,掌握这套框架+技巧就够了!
  • Vue面试中,经常会被问到的面试题/Vue知识点整理,收藏这篇就够了
  • 复习2——线程(pthread)
  • 【DPFSP问题】基于matlab鳄鱼伏击算法CAOA求解分布式置换流水车间调度DPFSP【含Matlab源码 14744期】
  • 格雷厄姆特价股票策略在新能源行业的应用挑战
  • 毕业论文写不下去?百考通AI平台,一句话生成完整初稿,助你高效通关!
  • 【NWFSP问题】鳄鱼伏击算法CAOA求解零等待流水车间调度问题NWFSP【含Matlab源码 14745期】
  • 还在手动回复希音咨询?RPA+AI自动客服,效率提升30倍![特殊字符]
  • AI应用开发全景图:从LLM到Agent的硬核指南!这些大模型核心概念你必须懂
  • 揭秘Open-AutoGLM如何实现毫秒级快递轨迹更新:技术架构全解析
  • 换个角度看境外支付系统:警惕金融风险之安全测试实践