原题连接

题目描述

给定一个整数数组\(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. C# 保留两位“有效数字”,而不是两位“小数”

    1.问题描述: 最近在处理软件结果显示时,发现如果利用 Math.Round(Number,N) 取N为小数时,有的结果不能显示完全 比如:15.3245 和 0.00106 两个数字,如果 N=2 ...

  2. 逆序对 -- cogs1438 火柴排队

    题目链接:http://cogs.pro:8081/cogs/problem/problem.php?pid=vimiQkqjU [题目描述] 样例一输入: 4 2 3 1 4 3 2 1 4 样例二 ...

  3. Java实验报告&&课程报告

    Java实验报告 班级 计算机科学与技术二班 学号 20188450 姓名 李代传 完成时间 2019/9/19 评分等级 实验二 Java简单类与对象 实验目的 掌握类的定义,熟悉属性.构造函数.方 ...

  4. Count Different Palindromic Subsequences

    Given a string S, find the number of different non-empty palindromic subsequences in S, and return t ...

  5. [转帖]nginx 80端口重定向 转发到443端口

    nginx 80端口重定向到443端口 2017年05月16日 13:53:58 幸福丶如此 阅读数 33387   版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文 ...

  6. mysql CPU太高排查办法

    [1]问题描述 首先,查看top,下图来自网络 为什么会有%CPU 375??? 还可以超过100%的? 这是因为,有多核CPU.如图,top后,按数字1,即可出现下图. [2]排查办法(当前CPU爆 ...

  7. mysql函数使用报错

    This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its de 错误解决办法 解决办法也有两种,第一种是在创建 ...

  8. 小记--------spark的两种提交模式

    spark的两种提交模式:yarn-cluster . yarn-client 图解

  9. SQLite基础-4.数据定义语言(DDL)

    目录 一.创建数据库 1. 创建方式 2. 数据库命名规范 二. 创建表 1. 基本用法 2. 数据表命名规范 3. 字段命名规范 三. 删除表 一.创建数据库 1. 创建方式 在第二章中我们讲了如何 ...

  10. 【LOJ】#3036. 「JOISC 2019 Day3」指定城市

    LOJ#3036. 「JOISC 2019 Day3」指定城市 一个点的可以dp出来 两个点也可以dp出来 后面的就是在两个点的情况下选一条最长的链加进去,用线段树维护即可 #include < ...