news 2026/3/10 2:21:14

UVa 11166 Power Signs

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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串转换为更少的非零数字,并且这种转换可以连锁进行,从而得到全局最优解。算法的时间复杂度和空间复杂度都是线性的,适合处理大规模的输入数据。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/7 0:31:09

9 个降AI率工具,本科生高效降AIGC指南

9 个降AI率工具&#xff0c;本科生高效降AIGC指南 AI降重工具&#xff1a;高效降低AIGC率&#xff0c;让论文更自然 在当今学术写作中&#xff0c;越来越多的本科生开始使用AI生成内容来辅助论文写作。然而&#xff0c;随之而来的AIGC率过高、查重率偏高以及AI痕迹明显等问题&a…

作者头像 李华
网站建设 2026/3/4 6:14:29

BetterYeah智能体开发:插件概述

什么是插件当前大多数大模型使用的都是陈旧的语料进行训练&#xff0c;真实场景中&#xff0c;我们往往需要外部的数据来与LLM交互。插件是BetterYeah AI平台封装好提供给用户的内置扩展功能&#xff0c;它可以帮助用户轻松连接外部数据&#xff0c;和大模型协同构建更强大的功…

作者头像 李华
网站建设 2026/3/4 9:05:27

wsl使用git

前言&#xff1a;文章类型 > 笔记 安装git sudo apt-get install git 查看版本&#xff08;只用前面那句就行&#xff09; git --version; git credential-manager --version 用户配置 git config --global user.name "Your Name" git config --global user…

作者头像 李华
网站建设 2026/3/4 3:43:41

[特殊字符] 深入了解 Flutter:构建跨平台应用的利器

#> *作者&#xff1a;AI助手 | 发布日期&#xff1a;2025年4月*![Flutter Logo](https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Flutter_logo.png/800px-Flutter_logo.png) *图1&#xff1a;Flutter 官方 Logo*## 一、什么是 Flutter&#xff1f;**Flutter*…

作者头像 李华
网站建设 2026/3/4 12:39:10

6个高效AI论文网站盘点,智能改写功能让重复率直降

开头总结工具对比&#xff08;技能4&#xff09; &#xfffd;&#xfffd; 为帮助学生们快速选出最适合的AI论文工具&#xff0c;我从处理速度、降重效果和核心优势三个维度&#xff0c;对比了6款热门网站&#xff0c;数据基于实际使用案例&#xff1a;工具名称处理速度降重幅…

作者头像 李华
网站建设 2026/3/4 7:27:24

西门子Smart200昆仑技创7寸触摸屏的全面实战项目:新手首选

西门子smart200 昆仑技创的7寸触摸屏&#xff0c;汇川伺服雷赛步进脉冲控制&#xff0c;两路模拟量测量输入&#xff0c;国产机器人modbus tcp 通讯 全面实战项目&#xff0c;最适合新手入门练手学习。 外触摸屏软件3.3.2.6187最近在搞自动化项目的老铁们注意了&#xff01;今天…

作者头像 李华