YbtOJ20029 最大权值

作为今天膜你抄模拟赛上唯一切掉的题目,小w在此氵一篇题解。

链接

比赛中的题目,题库还没有

题目

题目描述

有一个长度为\(n\)的实数序列,下标从\(1\)开始,其中第\(k\)个位置的实数为\(p\cdot(sin(a\cdot k+b)+cos(c\cdot +d)+2)\)\(sin\)\(cos\)采用弧度制,其中\(p,a,b,c,d\)均为给定的整数。

你需要从这个序列中选择两个位置(可以相同),使前边的位置上的数字减去后边的位置上的数字最大。

如果选择了两个相同的位置,那么差为\(0\)

输入格式

从文件weight.in中读入数据。

一行六个整数\(p,a,b,c,d,n\)

输出格式

输出到文件weight.out中。

一行一个实数表示最大的差值,保留六位小数。

样例

小w破天荒地给了样例。

样例输入

100 432 406 867 60 1000

样例输出

399.303813

数据范围与提示

对于\(30\%\)的数据,\(1\leq p,a,b,c,d\leq 1000\)\(1\leq n \leq 1000\)

对于\(100\%\)的数据,\(1\leq p,a,b,c,d\leq 1000\)\(1\leq n \leq 10^6\)

思路

这道题居然后\(sin\)\(cos\)!小w哭了,于是试了试cmath

发现,果然有可以!

那我们就读入,然后处理,最后sort一遍排个序,用最大值减去最小值就好了呗~

\(Code\) \(1\)

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

#define MAXN 1000007

double qwq[MAXN] = {0.000000};

int p, a, b, c, d, n;

int main()
{
    freopen("weight.in", "r", stdin);
    freopen("weight.out", "w", stdout);
    scanf("%d%d%d%d%d%d", &p, &a, &b, &c, &d, &n);
    for (int i = 1; i <= n; i++)
    {
        qwq[i] = p * (sin(a * i + b) + cos(c * i + d) + 2);
    }
    sort(qwq + 1, qwq + 1 + n);
    printf("%0.6lf", qwq[n] - qwq[1]);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

复杂度\(O(nlogn)\)

一切看起来都是辣么完美。

但是!

但是

使前边的位置上的数字减去后边的位置上的数字最大

也就是说,顺序并不能打乱!

也就是说,不能用sort

那么,我们换个思路

思路 \(2\)

我们先考虑打暴力,直接两重循环枚举每两个数的差然后取最大值。

\(Code\) \(2\)

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

#define MAXN 1000007

double qwq[MAXN] = {0.000000};

int p, a, b, c, d, n;

int main()
{
    freopen("weight.in", "r", stdin);
    freopen("weight.out", "w", stdout);
    scanf("%d%d%d%d%d%d", &p, &a, &b, &c, &d, &n);
    for (int i = 1; i <= n; i++)
    {
        qwq[i] = p * (sin(a * i + b) + cos(c * i + d) + 2);
    }
    double maxn = -MAXN;
    for (int i = 1; i <= n; i++)
    {
        for (int j = i; j <= n; j++)
        {
            if (qwq[i] - qwq[j] > maxn)
            {
                maxn = qwq[i] - qwq[j];
            }
        }
    }
    printf("%0.6lf", maxn);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

这样的话……复杂度\(O(n^2)\)

太慢了啊喂!

思路 \(3\)

这时,小w灵机一动!我们可以直接把处理放到预处理中!

我们在预处理的循环中,找出目前最大值的下标,然后用目前最大值减去目前的值,若比之前最大值减目前的值大,就更新,最后输出。

\(Code\) \(3(AC)\)

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

#define MAXN 1000007

double qwq[MAXN] = { 0.000000 };
double maxn = -MAXN;
int p, a, b, c, d, n, awa;

int main()
{
    freopen("weight.in", "r", stdin);
    freopen("weight.out", "w", stdout);
    scanf("%d%d%d%d%d%d", &p, &a, &b, &c, &d, &n);
    for (int i = 1; i <= n; i++)
    {
        qwq[i] = p * (sin(a * i + b) + cos(c * i + d) + 2);
        if (qwq[awa] - qwq[i] > maxn)
        {
            maxn = qwq[awa] - qwq[i];
        }
        if (qwq[i] > qwq[awa])
        {
            awa = i;
        }
    }
    printf("%0.6lf", maxn);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

这样,复杂度成功降到\(O(n)\)

题解 · 完

posted @ 2020-11-14 20:07  W-RB  阅读(85)  评论(0编辑  收藏  举报