HDU1709(母函数)

题意是给你n个砝码问能在一个天平上称多少种重量。

砝码可以放在天平的两边,很容易想到用指数的正负表示放在左边还是右边,但是数组下标不可能是负数,可以用1w表示没有放砝码,比1w多多少就表示右边重多少,比1w少多少就表示左边重多少,然后就简单了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 21111
#define add 10000

long long a[maxn], b[maxn];
int n, num[111];
int c[11], Max;
bool vis[maxn/2];
int ans[maxn/2];

int main () {
    //freopen ("data.txt", "r", stdin);
    while (cin >> n) {
        Max = 0;
        for (int i = 1; i <= n; i++) {
            cin >> num[i];
            Max += num[i];
        }
        memset (a, 0, sizeof a);
        a[add] = 1, a[add+num[1]] = 1, a[add-num[1]] = 1;
        for (int i = 2; i <= n; i++) {
            memset (b, 0, sizeof b);
            for (int j = 0; j <= Max+add; j++)
                b[j] = a[j];
            for (int j = 0; j+num[i] <= Max+add; j++)
                b[j+num[i]] += a[j];
            for (int j = 0; j <= Max+add; j++)
                if (j-num[i] >= 0) b[j-num[i]] += a[j];
            for (int j = 0; j <= Max+add; j++)
                a[j] = b[j];
        }
        memset (vis, 0, sizeof (vis));
        for (int i = add+1; i <= Max+add; i++) if (a[i])
            vis[i-add] = 1;
        for (int i = add-1; i >= add-Max; i--) if (a[i])
            vis[add-i] = 1;
        int cnt = 0;
        for (int i = 1; i <= Max; i++) if (!vis[i])
            ans[++cnt] = i;
        cout << cnt << endl;
        for (int i = 1; i <= cnt-1; i++)
            cout <<ans[i] << " ";
        if (cnt) cout << ans[cnt] << endl;
    }
    return 0;
}


你可能感兴趣的:(HDU1709(母函数))