题目大意:

有一个a数组,将它的任意两个元素求一次和,得到的所有值和a数组里原来的所有数全部存到b数组里面,现在给你b数组,让你求出对应的a数组并按照从小到大的顺序输出。

分析:

首先把b数组从小到大排序处理,之后,b数组里最小的两个一定是a数组里的数,取出这两个数 b[1]、b[2] 然后删除 a[1]+a[2],再取出 b 中当前最小的,即为 a[3] ,在删除a[1] + a[3]、a[2]+a[3] …… 以此类推,直到取出了 b 中的所有 a 。关于如何删除,我选择用优先队列存储当前已经确定的所有 a 两两组合所能产生的所有 b ,在每一次要取最小值的时候,判断当前b的值是否等于队首,如果等于就删除队首,并且寻找下一个。

代码:

#include<bits/stdc++.h>
using namespace std;

struct cmp1{
    bool operator ()(int &a,int &b){
        return a>b;//最小值优先
    }
};

int a[1000];
int b[200000];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {

        for(int i=0;i<n;i++)
        {
            scanf("%d",&b[i]);
        }
        if(n==0)
        {
            printf("0\n");
            continue;
        }
        if(n==1)
        {
            printf("1\n%d\n",b[0]);
            continue;
        }
        sort(b,b+n);
        priority_queue<int,vector<int>,cmp1>q;
        a[0]=b[0];
        a[1]=b[1];
        q.push(a[0]+a[1]);
        int num=2;
        for(int i=2;i<n;i++)
        {
            if(q.empty()==1||b[i]!=q.top())
            {
                a[num]=b[i];
                for(int j=0;j<num;j++)
                {
                    q.push(a[num]+a[j]);
                    //cout<<"push"<<a[num]+a[j]<<endl;
                }
                num++;
            }
            else
            {
                //cout<<"pop:"<<b[i]<<endl;;
                q.pop();
            }
        }
        printf("%d\n",num);
        printf("%d",a[0]);
        for(int i=1;i<num;i++)
        {
            printf(" %d",a[i]);
        }
        printf("\n");
    }
}