原题连接

题目描述

给定一个整数数组\(a_1,a_2,…,a_n\)。

定义数组第 i 位上的减操作:把\(a_i\)和\(a_{i+1}\)换成\(a_i - a_{i+1}\)。

用con(a,i)表示减操作,可以表示为:

\[con(a,i)=[a_1,a_2,…,a_{i-1},a_i-a_{i+1},a_{i+2},…,a_n]
\]

长度为 n 的数组,经过 n-1 次减操作后,就可以得到一个整数t。

例如数组[12,10,4,3,5]经过如下操作可得到整数4:

\[con([12,10,4,3,5],2) = [12,6,3,5]
\\
con([12,6,3,5] ,3) = [12,6,-2]
\\
con([12,6,-2] ,2) = [12,8]
\\
con([12,8] ,1) = [4]
\]

现在给定数组以及目标整数,求完整操作过程。

输入格式

第1行包含两个整数n和t。

第2..n+1行:第i行包含数组中的第 i 个整数\(a_i\)。

输出格式

输出共n-1行,每行包含一个整数,第 i 行的整数表示第 i 次减操作的操作位置。

数据范围

\[1 \le n \le 100 \\
-10000 \le t \le 10000 \\
1 \le a_i \le 100 \\
\]

输入样例:

5 4
12
10
4
3
5

输出样例:

2
3
2
1

解题报告

题意理解

就是说,有一种操作,名为减操作,可以将合并相邻的两个数,比如说原来的数字是.

\[3,4,那么合并后变成-1
\]

也就是,

\[合并后的数字=前面一个数字-后面一个数字. \\
a[i]=a[i]-a[i-1] \\
然后删除a[i+1]
\]


思路解析

性质分析

我们发现,每一次减操作都会使得序列长度减少一个.

\[即原本长度len,然后一次减操作后就会变成len-1
\]

所以说,我们发现其实对于序列的最终结果\(t\),可以变成这种形式.

\[a[1]-a[2] \pm a[3] \pm a[4] \pm a[5]=t
\]

举个例子表示一下

\[a[1] \quad a[2] \quad a[3] \quad a[4] \quad a[5] \qquad 原序列\\
a[1] \quad a[2]-a[3] \quad a[4] \quad [5] \qquad 此时cut(2) \\
a[1] \quad a[2]-a[3] \quad a[4]-a[5] \qquad 此时cut(3) \\
a[1] \quad a[2]-a[3]-(a[4]-a[5]) \qquad 此时cut(2) \\
a[1]-(a[2]-a[3]-(a[4]-a[5])) \qquad 最后cut(1) \\
a[1]-a[2]+a[3]+a[4]-a[5] \qquad 处理后的答案序列
\]

我们发现

\[a[1]必须是+号,a[2]必须是-号
\]

对于

\[a[1]必须是+号
\]

因为我们发现,\(1\)的前面没有数,可以去进行减操作.

最后一次执行的必然是\(cut(1)\)操作

\(a[1]\)表示,我真的想要减操作,但是我就是没有数可以和我一起减操作.

然后我们再来康康为什么一定是

\[a[2]必须为-号
\]

其实道理和之前一样,

最后一次执行的必然是\(cut(1)\)操作.

\(a[2]\)表示,我真的是被迫的,\(cut(1)\)使得\(a[1]-a[2]\).


状态设置

这样我们将题目转换成了

一个数列,对于数组中的数,将一些正整数变为负数,使整个数组的和为t,最后输出将哪些数变为负数.

我们发现这道题目的数据范围

\[n \le 100 \\
-10000 \le t \le 10000 \\
\]

数据范围真的好小啊,开一个\(n*t\)的数据范围丝毫没有问题.

所以说我们不妨这么设置一个状态数组.

\[f[i][cnt] \quad 表示前i个数字的和为cnt \\
f[i][cnt]=1 \quad 表示第i个数前面是+号 \\
f[i][cnt]=-1 \quad 表示第i个数前面是-号 \\
\]

不过我们要注意一下,C++负数下标有可能性挂掉了,所以我们不得不让所有下标加上一个固定的大数字,保证最后的下标是一个正数.

此时最大的问题就是,如何反推出我们的cut操作?


反推路径
  1. 为什么有些数可以是正数?也就是前面是+号?

这是一个非常重要的问题,我们发现.

\[一个数字前面是+号,只有在它这一位进行cut操作.
\]

假如说我们第\(i\)位不进行\(cut\)操作,那么它前面一定不是\(+\)号.

一个数,前面不是加号,就是减号.

\[cut(i) \qquad a[i]-a[i+1] \\
cut(i-1) \qquad a[i-1]-a[i] \\
\]

只有当\(i-1\)位进行\(cut\)操作的时候,这个第\(i\)位才可以是减号.

这就让我们证明了.

\[一个数字前面是+号,只有在它这一位进行cut操作.
\]

所以找到每一个\(+\)号的位置,然后输出当前位置.

不过你要注意一下,输出应该是.

\[i-tot-1 \\
tot表示为当前有几个cut操作了 \\
\]


代码解析

#include<bits/stdc++.h>
using namespace std;
#define init() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);//读入优化
const int maxn=105,maxt=20086,hh=10000;//hh是我们的下标转移常数
int n,t,f[maxn][maxt],a[maxn],ans[maxn];
void dp()
{
f[1][a[1]+hh] = 1;//a[1]必然是正数
f[2][a[1]-a[2]+hh]=-1;//a[2]必然是
for(int i=3; i<=n; i++)
for(int j=-10000+hh; j<=10000+hh; j++)
{
if(f[i-1][j])//可以转移
{
f[i][a[i]+j]=1;//+号
f[i][j-a[i]]=-1;//-号
}
}
}
void out()
{
int s=hh+t;
for(int i=n; i>=2; i--)//回溯走路径,确定+,-号
{
ans[i]=f[i][s];
if(ans[i]==1)
s-=a[i];
else if(ans[i]==-1)
s+=a[i];
}
int cnt=0;
for(int i=2; i<=n; i++)
if(ans[i]==1)//是时候减操作了.
{
cout<<i-cnt-1<<endl;
cnt++;
}
for(int i=2; i<=n; i++)
if(ans[i]==-1)//寻找
cout<<1<<endl;
}
int main()
{
init();
cin>>n>>t;
for(int i=1; i<=n; i++)
cin>>a[i];
dp();
out();
return 0;
}

POJ1722 算法竞赛进阶指南 SUBSTRACT减操作的更多相关文章

  1. 算法竞赛进阶指南0x51 线性DP

    AcWing271. 杨老师的照相排列 思路 这是一个计数的题目,如果乱考虑,肯定会毫无头绪,所以我们从1号到最后一个依次进行安排. 经过反复实验,发现两个规律 每一行的同学必须是从左向右依次连续放置 ...

  2. 算法竞赛进阶指南0x35高斯消元与线性空间

    高斯消元 目录 高斯消元 ACWing207. 球形空间产生器(点击访问) 求解思路 代码 ACWing208. 开关问题(点击访问) 思路 代码 总结 欣赏 线性空间 定义 ACWing209. 装 ...

  3. 算法竞赛进阶指南0x34矩阵乘法

    文章目录 矩阵的相关性质再回顾 矩阵加速大法: ACWing205. 斐波那契 代码 ACWing206. 石头游戏 解题思路: 感受: 代码 矩阵的相关性质再回顾 对于一个矩阵 满足结合律 满足乘法 ...

  4. 《算法竞赛进阶指南》0x10 基本数据结构 Hash

    Hash的基本知识 字符串hash算法将字符串看成p进制数字,再将结果mod q例如:abcabcdefg 将字母转换位数字(1231234567)=(1*p9+2*p8+3*p7+1*p6+2*p5 ...

  5. 《算法竞赛进阶指南》1.4Hash

    137. 雪花雪花雪花 有N片雪花,每片雪花由六个角组成,每个角都有长度. 第i片雪花六个角的长度从某个角开始顺时针依次记为ai,1,ai,2,-,ai,6. 因为雪花的形状是封闭的环形,所以从任何一 ...

  6. bzoj 1787 && bzoj 1832: [Ahoi2008]Meet 紧急集合(倍增LCA)算法竞赛进阶指南

    题目描述 原题连接 Y岛风景美丽宜人,气候温和,物产丰富. Y岛上有N个城市(编号\(1,2,-,N\)),有\(N-1\)条城市间的道路连接着它们. 每一条道路都连接某两个城市. 幸运的是,小可可通 ...

  7. POJ1639 算法竞赛进阶指南 野餐规划

    题目描述 原题链接 一群小丑演员,以其出色的柔术表演,可以无限量的钻进同一辆汽车中,而闻名世界. 现在他们想要去公园玩耍,但是他们的经费非常紧缺. 他们将乘车前往公园,为了减少花费,他们决定选择一种合 ...

  8. 算法竞赛进阶指南 0x00 基本算法

    放在原来这个地方不太方便,影响阅读体验.为了读者能更好的刷题,另起一篇随笔. 0x00 基本算法 0x01 位运算 [题目][64位整数乘法] 知识点:快速幂思想的灵活运用 [题目][最短Hamilt ...

  9. 算法竞赛进阶指南--快速幂,求a^b mod p

    // 快速幂,求a^b mod p int power(int a, int b, int p) { int ans = 1; for (; b; b >>= 1) { if (b &am ...

随机推荐

  1. 架构模式:API组合

    架构模式: API组合 上下文 您已应用微服务架构模式和每服务数据库模式.因此,实现从多个服务连接数据的查询不再是直截了当的. 问题 如何在微服务架构中实现查询? 结论 通过定义API Compose ...

  2. springboot整合es客户端操作elasticsearch(五)

    springboot整合es客户端操作elasticsearch的总结: 客户端可以进行可以对所有文档进行查询,就是不加任何条件: SearchRequest searchRequest = new ...

  3. [转帖]mysql8.0忘记密码如何操作?

    mysql8.0忘记密码如何操作? https://www.cnblogs.com/gspsuccess/p/11245314.html mark 一下 上次竟然不知道怎么弄. 很不幸,刚安装了MYS ...

  4. Linux就该这么学——新手必须掌握的命令之文件目录管理命令组

    touch命令 用途 : 用于创建空白文件或设置文件的时间 格式 : touch [选项] [文件] 参数 作用 -a 仅修改”读取时间”(atime) -m 仅修改”修改时间”(mtime) -d ...

  5. Gson格式转换Integer变为Double类型问题解决

    问题描述 在前后端分离的开发模式下,前后端交互通常采用JSON格式数据.自然会涉及到json字符串与JAVA对象之间的转换.实现json字符串与Java对象相互转换的工具很多,常用的有Json.Gso ...

  6. 【原创】大数据基础之Kudu(5)kudu增加或删除目录/数据盘

    kudu加减数据盘不能直接修改配置fs_data_dirs后重启,否则会报错: Check failed: _s.ok() Bad status: Already present: FS layout ...

  7. python 列表反转

    反转: 将原列表反转,返回None: li = [1, 2, 3]li.reverse()print(li)# [3, 2, 1]1234不改变原列表,返回反转后的新列表: li = [1, 2, 3 ...

  8. centos7安装nginx服务

    Nginx发音引擎x是一个免费的开源高性能HTTP和反向代理服务器,负责处理互联网上一些最大的网站的负载. 本教程将教你如何在你的CentOS Linux 7.5机器上安装和管理Nginx. 安装Ng ...

  9. centos配置LVS

    LVS有三种工作模式:NAT, TUN, DR.  DR是三种工作模式中性能最高的,TUN次之. 本文记录LVS/TUN和LVS/DR工作模式的配置过程. 环境: 三台CentOS 7 x64 虚拟机 ...

  10. javascript立体学习指南

    javascript立体学习指南第一章:首先了解javascript 首先,什么是javascript? JavaStrip出生于1995年,是一种文本脚本语言,成都装修公司是一种动态的.弱类型的.基 ...