Codeforces 949E Binary Cards

传送门.

题解:

观察1:
一个序号x不会选超过一个。

假设选了x、x,可以通过选2x、-x替代

观察2:
选了序号x,就不会选-x,反过来也成立。

假设选了x,-x,可以通过选2x、-x替代

*lj样例就是来迷惑人的。

接下来怎么办呢?

暴力。

如果没有奇数,那么肯定不用1或者-1

用奇数的话,就枚举1还是-1,继续递归这个过程。

记得去重,这样的复杂度是 T(n)=2T(n/2)+nO(n log n) T ( n ) = 2 ∗ T ( n / 2 ) + n ≈ O ( n   l o g   n )

Code:

#include
#include
#include
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;

const int N = 1e5 + 5;

int n, a[N], d[N], b[21][N], a2[25], ans[N];

void dg(int x) {
    if(x > 20) {
        if(d[0] < ans[0])
            fo(i, 0, d[0]) ans[i] = d[i];
        return;
    }
    int pos = 0;
    fo(i, 1, n) pos |= a[i] & a2[x];
    if(!pos) dg(x + 1); else {
        int n0 = n;
        fo(i, 1, n0) b[x][i] = a[i];
        d[++ d[0]] = a2[x];
        fo(i, 1, n0) if(b[x][i] & a2[x])
            a[i] = b[x][i] - a2[x]; else a[i] = b[x][i];
        sort(a + 1, a + n0 + 1);

        n = 0;
        fo(i, 1, n0) if(i == 1 || a[i] != a[i - 1])
            a[++ n] = a[i];

        dg(x + 1);
        d[d[0]] = -a2[x];
        fo(i, 1, n0) if(b[x][i] & a2[x])
            a[i] = b[x][i] + a2[x]; else a[i] = b[x][i];

        n = 0;
        fo(i, 1, n0) if(i == 1 || a[i] != a[i - 1])
            a[++ n] = a[i];

        dg(x + 1);
        d[0] --;
    }
}

int main() {
    a2[0] = 1; fo(i, 1, 20) a2[i] = a2[i - 1] * 2;
    scanf("%d", &n);
    fo(i, 1, n) scanf("%d", &a[i]);
    ans[0] = 30; dg(0);
    printf("%d\n", ans[0]);
    fo(i, 1, ans[0]) printf("%d ", ans[i]);
}

你可能感兴趣的:(分治,杂题,CF)