Numbers

Numbers

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 549    Accepted Submission(s): 291


Problem Description
zk has n numbers a1,a2,...,an . For each (i,j) satisfying 1≤i<j≤n, zk generates a new number (ai+aj) . These new numbers could make up a new sequence b1b2,...,bn(n1)/2 .
LsF wants to make some trouble. While zk is sleeping, Lsf mixed up sequence a and b with random order so that zk can't figure out which numbers were in a or b. "I'm angry!", says zk.
Can you help zk find out which n numbers were originally in a?
 

Input
Multiple test cases(not exceed 10).
For each test case:
The first line is an integer m(0≤m≤125250), indicating the total length of a and b. It's guaranteed m can be formed as n(n+1)/2.
The second line contains m numbers, indicating the mixed sequence of a and b.
Each ai is in [1,10^9]
 

Output
For each test case, output two lines.
The first line is an integer n, indicating the length of sequence a;
The second line should contain n space-seprated integers a1,a2,...,an(a1a2...an) . These are numbers in sequence a.
It's guaranteed that there is only one solution for each case.
 

Sample Input
  
  
6 2 2 2 4 4 4 21 1 2 3 3 4 4 5 5 5 6 6 6 7 7 7 8 8 9 9 10 11
 

Sample Output
  
  
3 2 2 2 6 1 2 3 4 5 6
 

题意:

     给定一个数列,其大小为m,规定其是数列a与数列b的混合数列(乱序)。其中数列a的长度为n,规定m满足n*(n+1)/2。另外,规定b数列是任意两个a[i]与a[j]的和(i不等于j)。求a数列的长度及数列元素。输出元素需从大到小排列。其中a数列与b数列中的元素均可重复。


思路:

     由于给定的混合数列是乱序的,而我们需要输出一个有序的数列a,所以可以考虑用优先队列处理。

     混合数列为a与b的混合,而数列b恰好是数列a中任意两个数的和。混合数列大小为m,数列a大小为n,由于m满足n*(n+1)/2,由计算可得数列b的大小为n*(n-1)/2,由此可得数列b为数列a中所有数的两两组合所得和。细想可知,混合数列由小到大排序后,最小的两个数一定是数列a中的元素。然后再将两数相加所得和必是数列b中的元素,也一定存在于混合数列中,所以把这个和在混合数列中删去。处理混合数列中的所有元素,判断是a中的元素还是b中的元素,把所有的和删去留下的就是数列a。

     用一个优先队列存储混合数列ab,再用一个优先队列b存储现有a中所有元素两两结合后的所得和。先将ab中前两个元素弹出,再将这两个元素的和存在b中,比较b.top与ab.top,如果相等,则说明ab.top是b中的元素,不是a中的元素,所以直接弹出ab.top,再将b.top弹出;如果不相等,只能是ab.top<b.top,因为b中的元素一定全部存在在ab中,优先队列中所有元素有序,所以ab.top只能是小于等于b.top。当不等于时,说明ab.top是a中的元素,所以把ab.top加在a中,然后弹出ab.top。而每加入一个元素到a中,就要把这个元素与现存的a中的所有元素相加,再把所得和加入优先队列b中,再判断下一个元素是否与b.top相等。直到ab中所有的元素判断完为止。其中,当b数列为空时,说明当前a中的所有元素两两和都已经在ab中删去,所以ab.top一定为a中的元素。持续处理直至ab为空。


下面贴上代码:

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

const int maxn=125500;
priority_queue<int, vector<int>,greater<int> > ab; //混合数列ab
priority_queue<int, vector<int>,greater<int> > b; //和集b
int a[maxn]; //a数列

int main()
{
    int m;
    while(~scanf("%d",&m))
    {
        int number;
        for(int i=0; i<m; i++)
        {
            scanf("%d",&number);
            ab.push(number);
        }

        //ab里面最小的两个数一定存在于a中
        a[0]=ab.top();
        ab.pop();
        a[1]=ab.top();
        ab.pop();

        b.push(a[0]+a[1]);

        int n=2; //数列a长度为n
        while(!ab.empty())
        {
            if(b.empty()) //如果b为空,就直接将ab的top弹到a里面
            {
                a[n++]=ab.top();
                for(int i=0; i<n-1; i++)
                    b.push(a[i]+ab.top());
                ab.pop();
            }

            else if(ab.top()==b.top())
            {
                ab.pop();
                b.pop();
            }
            else //由于m一定满足n(n+1)/2,则b中的数在ab中一定存在,又因为ab和b均为优先队列,故若ab.top!=b.top,则ab.top一定小于b.top,故直接将ab的top弹到a里面
            {
                a[n++]=ab.top();
                for(int i=0; i<n-1; i++)
                    b.push(a[i]+ab.top());
                ab.pop();
            }
        }

        printf("%d\n",n);

        for(int i=0; i<n-1; i++)
            printf("%d ",a[i]);
        printf("%d\n",a[n-1]);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值