HDU6168-Numbers

本文介绍了一种算法,该算法能够从混合同一数列及其两两求和后的数列中,还原出原始的数列。通过使用multiset数据结构进行排序和逐个排除已知组合的方式,确保了算法的有效性和唯一性。

Numbers

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

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 b1,b2,…,bn(n−1)/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(a1≤a2≤…≤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

Source
2017 Multi-University Training Contest - Team 9

题目大意:给出一个数列 a ,将其任意两项相加得到数列b,给出数列 a,b 混合后的数列,问原数列 a 为多少。ai[1,109]
解题思路:将给出的数列丢到 multiset 里,取出第一项作为 a1 ,塞进答案里,在取出 multiset 第一项 a2 ,在 multiset 删除 a2 与答案里所有的数之和(若有重复只删除第一个),在把 a2 塞进答案,以此类推。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<vector>
#include<queue>
using namespace std;
const int MAXN=2e5+5;
multiset<int> ms;
vector<int> ans;

int main()
{
    int m;
    while(scanf("%d",&m)!=EOF)
    {
        ms.clear();ans.clear();
        int tmp;
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&tmp);
            ms.insert(tmp);
        }
        auto p=ms.begin();ans.push_back(*p);ms.erase(p);
        while(!ms.empty())
        {
            p=ms.begin();
            for(auto i:ans)
            {
                ms.erase(ms.find(i+*p));
            }
            ans.push_back(*p);ms.erase(p);
        }
        int sz=ans.size();
        printf("%d\n",sz);
        for(int i=0;i<sz;i++)
        {
            printf("%d%c",ans[i],i==sz-1?'\n':' ');
        }
    }
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值