25 P10960 subtract 题解

subtract

题面

现有一个数列 \(\{a_n\}\ (2 \le n,a_i \le 100)\),你需要对它进行 \(n-1\) 次操作。其中第 \(i\) 次操作是:

  1. 选择一个正整数 \(t\ (1 \le t \le n-i)\)
  2. 计算 \(d=a_t-a_{t+1}\)
  3. 删除 \(a_t,a_{t+1}\) 两项;
  4. 在原来 \(a_t\) 的位置插入一项 \(d\)

试构造一种操作方案,使得 \(n-1\) 次操作后数列中剩下的那个数恰好等于给定的数 \(T\ (|T| \le 10^4)\)(保证有解)。

题解

这道题个人感觉更偏向构造

先给结论对于数列中的数,最后一定要么是 + ,要么是 - ,对于 \(a_1\) 只能是 + ,对于 \(a_2\) 只能是 -

也就是最后的数列是形如 \(a_1 - a_2 \pm a_3 \pm a_4 ... \pm a_n\)

其实原来的那些操作都可以看作是在数列中加括号,比如一开始的数列是 \(a_1 - a_2 - a_3 - a_4 ... -a_n\)

我们可以通过加括号将除第一个以外的某些负号变成正号

\(a_1 - ((a_2 - a_3) - a_4) ... -a_n = a_1 - a_2 + a_3 + a_4 ... - a_n\)

这样的话,题目就变成了一个背包问题,每个物品可以 +/- ,最后倒推一下各个位置的符号

如果是正号,我们可以让 \(a_{i - 1} - a_i\) ,然后再让 \(a_{i - 2} - a_{i - 1}\) 这样 \(i\) 位置就变成了负号,所以我们只需将所有正号消掉,然后剩下全是负号,直接一直操作第一个元素即可

code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>

using namespace std;

const int N = 110, M = 1e4;

int n, m;
int a[N], c[N];
bool f[N][M * 2 + 30];

int main () {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i];
    }
    int base = 1e4 + 10;
    f[2][base + a[1] - a[2]] = 1;
    for (int i = 3; i <= n; i ++) {
        //减号
        for (int j = base - M; j <= base + M - a[i]; j ++) {
            f[i][j] |= f[i - 1][j + a[i]];
        }
        //加号
        for (int j = base - M + a[i]; j <= base + M; j ++) {
            f[i][j] |= f[i - 1][j - a[i]];
        }
    }

    {
        int i = n, j = base + m;
        while (i >= 3) {
            if (f[i - 1][j + a[i]]) {
                c[i] = -1;
                j = j + a[i];
                i --;
            } else {
                c[i] = 1;
                j = j - a[i];
                i --;
            }
        }
    }

    c[1] = 1, c[2] = -1;
    int cnt = 0;
    for (int i = 2; i <= n; i ++) {
        if (c[i] == 1) {
            printf ("%d\n", i - cnt - 1);
            cnt ++;
        }
    }
    for (int i = 1; i <= n - cnt - 1; i ++) {
        cout << 1 << endl;
    }

    return 0;
}
posted @ 2025-10-05 18:06  michaele  阅读(7)  评论(0)    收藏  举报