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)\)!
题解 · 完
本文作者:W-RB,本文遵循 CC BY-NC 协议,转载请注明原文链接:https://www.cnblogs.com/w-rb/p/13974498.html和作者W-RB,且仅允许在非商业情况下使用