减操作

题面

给定一个整数数组a1,a2,…,an。

定义数组第 i 位上的减操作:把ai和ai+1换成ai−ai+1。

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

con(a,i)=[a1,a2,…,ai−1,ai−ai+1,ai+2,…,an]
长度为 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 个整数ai。

输出格式

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

数据范围

1≤n≤100,
−10000≤t≤10000,
1≤ai≤100

输入样例:

5 4
12
10
4
3
5

输出样例:

2
3
2
1

题解

自己随便画一下会发现 最后是

a[1] - a[2] ± a[3] ± a[4] ... ± a[n]

发现 n * ai范围 挺小, 明显是线性dp

#include <bits/stdc++.h>
using namespace std;

const int maxn = 105;
const int p = 10000;

int n, t, a[maxn], f[maxn][p << 1 | 1], ans[maxn];

int main()
{
    cin >> n >> t;
    for (int i = 1;i <= n; ++i) cin >> a[i];
    
    f[1][p + a[1]] = 1; f[2][a[1] - a[2] + p] = -1;
    for (int i = 3; i <= n; ++i)
        for (int j = 0; j <= (p << 1); ++j)
           if(f[i - 1][j])
           {
              if (a[i] + j >= 0 && a[i] + j <= (p << 1)) f[i][a[i] + j] = 1;
              if (j - a[i] >= 0 && j - a[i] <= (p << 1)) f[i][j - a[i]] = -1;
           }
           
    for (int i = n, cur = p + t; i >= 2; cur -= a[i] * ans[i--]) 
        ans[i] = f[i][cur];
    
    for (int i = 2, cnt = 0; i <= n; ++i) 
        if(ans[i] == 1) cout << i - (cnt++) - 1 << '\n';
    
    for(int i = 2; i <= n; ++i) 
        if(ans[i] == -1) cout<< 1 << '\n';
    return 0;
}
posted @ 2020-05-06 22:29  洛绫璃  阅读(231)  评论(0编辑  收藏  举报