首页 > 代码库 > codevs 1245 最小的N个和

codevs 1245 最小的N个和

技术分享
 
题目描述 Description

有两个长度为 N 的序列 A 和 B,在 A 和 B 中各任取一个数可以得到 N^2 个和,求这N^2 个和中最小的 N个。

输入描述 Input Description

第一行输入一个正整数N;第二行N个整数Ai 且Ai≤10^9;第三行N个整数Bi,
且Bi≤10^9

输出描述 Output Description

输出仅一行,包含 n 个整数,从小到大输出这 N个最小的和,相邻数字之间用
空格隔开。

样例输入 Sample Input

5

1 3 2 4 5 
6 3 4 1 7

样例输出 Sample Output

2 3 4 4 5

***************************************************************

方法::

暴力枚举即可

可以推出,将两个初始数列排序后,对于a数列中第i个,与他配对的只需要枚举到b数列的第n/i个即可

原因是::

若第i个再最后输出的序列中最多包含的尤其相加的结果的个数是x个,则a【】前面的所有元素所能配出比 第i个所配出的个数都多或相等(举个例子)

A---------1 3 3 5 9 11

B---------1 2 3 4 5 6

假如我们找到了a的第三个元素,我们只需要和b的前两个配对即可,因为a【1】,a【2】与b的前两个的配对不可能大于第三个元素的配对,这样我们就已经找出了至少6个最小的,

满足题目要求了有木有。

这样我们用数组记录下找出的对的值,最后排一遍序就行了

代码::

#include<cstdio>
#include<algorithm>
#define maxn 100001
using namespace std;
int a[maxn];
int b[maxn];
int c[maxn*10];
int cha[maxn];
int top = 0;
int n;
int read()
{
    int num = 0;
    char c = getchar();
    int f = 1;
    while(c < 0||c > 9)
    {
        if(c == -)f = -1;
        c = getchar();
    }
    while(c >= 0 && c <= 9)
    {
        num *= 10;
        num += c - 0;
        c = getchar();
    }
    return num * f;
}
int main()
{
    n = read();    
    for(int i = 1;i <= n; i ++)
    {
        a[i] = read();
    }
    for(int i = 1;i <= n; i ++)
    {
        b[i] = read();
    }
    sort(a + 1,a + n + 1);
    sort(b + 1,b + n + 1);
    for(int i = 1;i <= n;i ++)
    {
        int zz = n / i ;
        //if( i > 10 )zz = min(zz,10);
        for(int j = 1;j <= zz;j ++)
        { 
            cha[++ top] = a[i] + b[j];
        }
    }
    sort(cha + 1,cha + top + 1);
    for(int i = 1; i <= n; i ++)
    {
        printf("%d ",cha[i]);
    }
    return 0;
} 

 

codevs 1245 最小的N个和