UVA - 1614 Hell on the Markets(贪心 + 结论)

点击打开题目链接
题目大意
给定n个数,满足1<=a[i]<=i;
使其中某些数变成倒数使得n个数总和为0;

思路:
结论:n个数可以组成1~sum[n]的任意数
证明:
当n = 1时, a[1] = 1 = sum[1] 满足;
假设当n = k时满足;
当n = k + 1时:
sum[k+1] = sum[k] + a[k+1];
因此只需证明能凑出sum[k]+1 ~ sum[k+1]的所有整数即可。
设p满足1<=p<=a[k+1]
∵sum[k] + p = sum[k] + a[k+1] - (a[k+1] - p);
并且 1<=a[k]<=k
∴sum[k] >= k && a[k+1] - p <= k;
因为前k个数能凑出a[k+1] - p;
∴前n个数能凑出1~sum[n]的所有数。

代码:

#include<bits/stdc++.h>

using namespace std;
const int maxn = 100000 + 5;
typedef long long ll;
struct a{
    int id, x;
    bool operator < (const a & rhs) const {
        return x > rhs.x;
    }
}p[maxn];
int po[maxn];
int n;

int main() {
    //ios::sync_with_stdio(false),cin.tie(0);
    //freopen("D:\\input.txt", "r", stdin);
    //freopen("D:\\output.txt", "w", stdout);
    while(cin >> n) {
        memset(p, 0, sizeof(p));
        memset(po, 0, sizeof(po));
        ll sum = 0;
        for(int i = 0; i < n; i++) {
            cin >> p[i].x;
            p[i].id = i;
            sum += p[i].x;
        }
        if(sum % 2) cout << "No" << endl;
        else {
            cout << "Yes"  << endl;
            sort(p, p + n);
            sum = sum / 2;
            for(int i = 0; i < n; i++) {
                if(p[i].x <= sum) {
                    po[p[i].id] = 1;
                    sum -= p[i].x;
                }
                else po[p[i].id] = -1;
            }
            //cout << po[1] << ' ' << po[2] << ' ' << po[3] << ' ' << po[4] << "QAQ"  << endl;
            for(int i = 0; i < n; i++) {
                if(i == 0) printf("%d", po[i]);
                else printf(" %d", po[i]);
            }
            printf("\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/l1832876815/article/details/79485695