YbtOJ20029 最大权值

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

链接

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

题目

题目描述

有一个长度为(n)的实数序列,下标从(1)开始,其中第(k)个位置的实数为(pcdot(sin(acdot k+b)+cos(ccdot +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\%)的数据,(1leq p,a,b,c,dleq 1000)(1leq n leq 1000)

对于(100\%)的数据,(1leq p,a,b,c,dleq 1000)(1leq 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))

题解 · 完

原文地址:https://www.cnblogs.com/w-rb/p/13974498.html