UVA - 1614 Hell on the Markets 贪心+推理

题目大意:给出n个数字,第i个数字的大小满足 1 <= ai <= i,要求确定每个数的正负号,使得所有数的总和为0

解题思路:总和为0,那sum % 2 == 0

接着分析一下,因为和为0,所以sum / 2要能通过这n个数得到,那就枚举看看能不能得到

从大到小枚举,取当前这个数的个数和(sum/当前这个数)的值的最小值,接着sum减去这个最小值乘于当前值

如果(sum/当前这个数)是取得的最小值,那么分两种情况

一种是能除尽的,那么(sum - 最小值 * 当前这个数)就刚好为0了,也就是sum/2这个数能求得到,符合了

一种是不能除尽的,那么(sum - 最小值 * 当前这个数)就会有剩下,因为是从大到小枚举的,所以剩下的值只能看那些小值能不能相加得到了

#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 100010
int num[maxn], cnt[maxn], cnt2[maxn];

int main() {
    int n;
    while(scanf("%d", &n) == 1) {
        long long sum = 0;
        int MAX  = 0;
        for(int i = 1; i <= n; i++)
            cnt[i] = cnt2[i] = 0;

        for(int i = 1; i <= n; i++) {
            scanf("%d", &num[i]);
            sum += num[i];
            cnt[num[i]]++;
            MAX = max(MAX, num[i]);
        }

        if(sum % 2) {
            printf("No\n");
            continue;
        }
        bool flag = true;
        sum /= 2;
        for(int i = MAX; i >= 1 && flag ; i--) {
            cnt2[i] = min((long long)cnt[i], sum / i);
            sum -= (long long)cnt2[i] * i;
            if(sum == 0)
                flag = false;
        }
        if(flag) {
            printf("No\n");
            continue;
        }
        else {
            printf("Yes\n");
            for(int i = 1; i <= n; i++) {
                if(i == 1) {
                    if(cnt2[num[i]] > 0) {
                        printf("1");
                        cnt2[num[i]]--;
                    }
                    else
                        printf("-1");
                }
                else {
                    if(cnt2[num[i]] > 0) {
                        printf(" 1");
                        cnt2[num[i]]--;
                    }
                    else
                        printf(" -1");
                }
            }
            printf("\n");
        }
    }
    return 0;
}
时间: 2024-08-07 04:32:54

UVA - 1614 Hell on the Markets 贪心+推理的相关文章

UVA 1614 - Hell on the Markets 奇怪的股市(贪心,结论)

先证明一个结论吧,对于1≤ai≤i+1,一定可以表示出1~sum[i]中的任意一个数. 对于i=1显然成立, 假设对于i=k结论成立,那么对于i=k+1来说,只要证明sum[k]+i,1≤i≤ak+1可以凑出来就行了. 因为sum[k]+i≥k+1,且1≤ak+1≤k+1,所以可以先选一个ak+1,剩下的0≤sum[k]+i-ak+1≤sum[k]一定是可以有前面的数字凑出来的. 这就证明了贪心的正确性. #include<bits/stdc++.h> using namespace std;

Uva - 1614 - Hell on the Markets

Most financial institutions had become insolvent during financial crisis and went bankrupt or were bought by larger institutions, usually by banks. By the end of financial crisis of all the financial institutions only two banks still continue to oper

uva:10700 - Camel trading(贪心)

题目:10700 - Camel trading 题目大意:给出一些表达式,表达式由数字和加号乘号组成,数字范围[1,20].这些表达式可能缺少了括号,问这样的表达式加上括号后能得到的最大值和最小值. 解题思路:因为这些数的都是正整数,所以可以用贪心.不然看出最大值就是先做完加法在做乘法,最小值就是先做乘法在做加法.注意这里的数值要用long long 因为比表达式的值可能会超过int. 代码: #include <stdio.h> #include <string.h> cons

UVA 1016 - Silly Sort(置换分解+贪心)

UVA 1016 - Silly Sort 题目链接 题意:给定一个序列,数字都不同,每次可以交换两个数字,交换的代价为两数之和,要求出把这个序列变成递增最小代价 思路:利用置换的分解原理,可以把序列的每条循环单独考虑,对于每条循环而言,不断交换肯定每个数字至少会换到一次,再利用贪心的思想,如果每次拿循环中的最小值去置换,那么就是这个最小值会用长度-1次,而剩下的数字各一次,注意这里还有一种可能优的方法,就是先把整个序列中的最小值换到该循环中,等置换完再换出去,两种都考虑进来即可 代码: #in

·UVa」 11292 - Dragon of Loowater( 贪心 )

Problem C: The Dragon of Loowater Once upon a time, in the Kingdom of Loowater, a minor nuisance turned into a major problem. The shores of Rellau Creek in central Loowater had always been a prime breeding ground for geese. Due to the lack of predato

UVA 11246 - K-Multiple Free set(数论推理)

UVA 11246 - K-Multiple Free set 题目链接 题意:一个{1..n}的集合,求一个子集合,使得元素个数最多,并且不存在有两个元素x1 * k = x2,求出最多的元素个数是多少 思路:推理一下, 一开始n个 先要删除k倍的,删除为{k, 2k, 3k, 4k, 5k, 6k...},会删掉多余的k^2,因此在加回k^2倍的数 然后现在集合中会出现情况的只有k^2的倍数,因此对k^2倍的数字看成一个新集合反复做这个操作即可,因此最后答案为n - n / k + n /

UVA 12124 UVAlive 3971 Assemble(二分 + 贪心)

先从中找出性能最好的那个数, 在用钱比较少的去组合,能组出来就表明答案在mid的右边,反之在左边, #include<string.h> #include<map> #include<stdio.h> #include<iostream> #include<algorithm> using namespace std; map<string,int> vic;//以字符映射数字 int end,start; int num; int

【uva 1614】Hell on the Markets(算法效率--贪心)

题意:有一个长度为N的序列A,满足1≤Ai≤i,每个数的正负号不知.请输出一种正负号的情况,使得所有数的和为0.(N≤100000) 解法:(我本来只想静静地继续做一个口胡选手...←_← 但是因为这题的贪心实在是太厉害了!我就单看,就盯了题解半小时以上...而代码又那么短,我就打了代码了...其实我又不太理解为什么一定要排序.) 贪心部分的理论依据:前i个数可以凑出1-sum[i]的所有整数. 证明:第二类数学归纳,n=1时成立,假设n=k之前所有项都成立,当n=k+1时.sum[k+1]=s

UVA-1614 Hell on the Markets(贪心+推理) (有待补充)

题目大意:一个整数序列a,1≤a[i]≤i.问能否通过在一些元素前加上负号,使得整个序列和为0. 题目分析:贪心.贪心策略:每次都先选最大的元素加负号(或保留,不加负号). 贪心依据:对于1≤a[i]≤i,1~sum[i]总能表示出来.   贪心依据证明:用数学归纳法证明,当i=1时,显然成立.假设当i=k时,也成立.当i=k+1时,(先证明到这儿,有空再补). 代码如下: # include<iostream> # include<cstdio> # include<cst