湖南工业大学第一届ACM竞赛 分糖果 位操作

                      分糖果

时间限制(普通/Java):1000MS/3000MS          运行内存限制:65536KByte
总提交:14            测试通过:11

描述

 

肖恩和帕特里克是兄弟,他们从他们的父母那里得到了很多糖果。每一块糖具有一个的正整数的价值,孩子们希望分他们得到的糖果。首先,肖恩将这些糖果分成两堆,并选择一堆给帕特里克。然后,帕特里克将尝试计算每堆的价值,其中每堆的价值是在那堆的糖果价值的总和,如果他觉得没有平等的价值,他将开始哭了起来。

不幸的是,帕特里克太小了,所以不能正确的计算。他只会二进制无进位的加法。比如说,他想算12(二进制为1100)加5(二进制为101),他会把最右边的两位加法算正确,但是第三位会忘记进位。(即0+0=0,0+1=1,1+0=1,1+1=0)

因此,帕特里克算125的结果为9下面几个是帕特里克算的结果:

5 + 4 = 1

7 + 9 = 14

50 + 10 = 56

肖恩数学很好,他想得到价值总和更高的糖果并且不让他的弟弟哭。如果可能,他会分成两个非空的糖果袋,让帕特里克认为,双方都有相同的值的糖果。给你每一袋糖果每一块糖果的价值,我们想知道是否可能让帕特里克相信他们得到糖果价值的总量是相同的。如果可能计算出肖恩能得到的最大的价值。


输入

第一行输入T(1<T<1000)组测试数据。接下来是T行,每行包含以下数据,N C1 C2 .. Cn
(N(2 ≤ N ≤ 1000)代表从父母那里得到糖果的总数,C(1 ≤ Ci ≤ 10^6)代表每块糖果的价值)

输出

若不能输出NO,若能则输出肖恩得到的最大的价值。

样例输入

2
5 1 2 3 4 5
3 3 5 6

样例输出

NO
11

  天哪, 刚看见这道题目,就觉得无从下手,只知道这是道跟数字过不去的题目,无进位加法,看似从未接触过,写成程序的话也是繁杂冗长,比赛时间宝贵,没有灵感还不是直接跳过这道题目,就这样放弃了这道题目。

  赛后,听了解题发布会,才知道这个要用异或位运算来处理 即 对应二进制中的每一位 1+1=0、0+0=0、1+0=1,0+1=1,而且更令人匪夷所思的是,判定题中是否能够平分成两半的条件就是把所有的数字二进制无进位相加,如果最后的结果 不为零 的话,那么说明这种分法不成立。 而如果相加的结果等于零的话,只需将最小的那个数给弟弟就可以了...... 这里又是一个比较神奇的地方,即N个数的二进制无进位加法结果为零的话,那么无论怎样去分开这N个数,分成的两部分的结果分别做无进位加法后的结果一样 例如 | 3 5 6 | ,  3(10) = 011(2)  , 5(10) = 101(2) , 6(10) = 110(2)  , 进行无进位加法后 101(2) + 110(2) = 011(2) = 3(10) ,这样一下来,代码就异常简单了 如下:

 

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<time.h>


int N,T;

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        int min=0x7fffffff,temp=0;
        int sum=0;
        scanf("%d",&N); 
        while(N--)
        {
            
            int c;
            scanf("%d",&c);
            min = min < c ? min : c;
            temp ^= c; 
            sum+=c;
        }
        if(temp!=0)
            puts("NO");
        else
            printf("%d\n",sum-min);
        
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Lyush/p/2048907.html