Vijos隐形的翅膀

162 阅读1分钟

Vijos隐形的翅膀

背景

小杉终于进入了天堂。他看到每个人都带着一双隐形翅膀,他也想要。

(小杉是怎么看到的?……)

描述

天使告诉小杉,每只翅膀都有长度,两只翅膀的长度之比越接近黄金分割比例,就越完美。

现在天使给了小杉N只翅膀,小杉想挑出一对最完美的。

格式

输入格式

每组测试数据的 第一行有一个数N(2<=N<=30000) 第二行有N个不超过1e5的正整数,表示N只翅膀的长度。

20%的数据N<=100

输出格式

对每组测试数据输出两个整数,表示小杉挑选出来的一对翅膀。

注意,比较短的在前,如果有多对翅膀的完美程度一样,请输出最小的一对。

样例1

样例输入1

4
2 3 4 6

Copy

样例输出1

2
3

Copy

限制

每个测试点1s

提示

你可以认为黄金分割比就是0.6180339887498949

分析

我们可以将所有数据从小到大快排,然后对于数组中的每个数a[i],去除以黄金分割比可以得到一个数,再在数组中找和所得数相近的数,用找到的数除以a[i],最后找和黄金分割比最相近的一组数。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath> using namespace std;

const double xyz = 0.6180339887498949;
int n;
double a[30005];
double ans = 9999999999.0;
int x, y;

int search(double e, int p)
{
    int l = p + 1, r = n;
    while (l <= r)
    {
        int mid = (l + r) / 2;
        if (a[mid] <= e)
            l = mid + 1;
        else
            r = mid - 1;
    }
    double w = fabs(a[l] - e);
    double b = fabs(a[l - 1] - e);
    double c = fabs(a[l + 1] - e);
    if (w < b && w < c)
        return l;
    else if (b < w && b < c)
        return l - 1;
    else
        return l + 1;
}

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    sort(a + 1, a + n + 1);
    for (int i = 1; i <= n; i++)
    {
        double t = (a[i] / (xyz));
        int k = search(t, i);
        double temp = fabs(a[i] / a[k] - xyz);
        if (temp < ans)
        {
            ans = temp;
            x = a[i];
            y = a[k];
        }
    }
    cout << x << endl
         << y << endl;
    return 0;
}