Description
给定商品成本 p0 和系数 k ,常数 n0 ,设价格为 p ,购买商品人数满足n1 =
⌊
n0 -k*p
⌋
其中 p , k 为实数, 0 n 为整数。
题目分为两部分:
1)可以设置一个价格,求最大利润。
2)可以设置两个价格, p1 , p2 ,有 n1 =
⌊
n0-k*p1
⌋
的人按 p1 购买,n2=
⌊
n0-k*p2
⌋
-n1 按 p2 购买,求最大利润。
题解:
解法一:因为是单峰函数,所以很显然可以用三分求出极值,但
是实现细节比较复杂。
解法二:最直观的想法是直接枚举 p ,求最大值。但是 p 是实
数,精度什么的不好处理。我们以 n1 为自变量,枚举 n1 的取值,
然后求最大值。第二部分也类似,枚举 n1 ,然后可以得到一个关
于 n2 的二次函数,这时直接用二次函数的相关知识就能求出最大
值(对称轴x=-
b2a
)
解法三:对于第一部分还有一个更简单的解法,直接可以从图像
中发现,当 p 取中点的时候利润是最大的。所以只需要取中点
和其上下取整的最大值就是答案。
这里重点介绍第二种解法:
补充一下一元二次函数求最值方面的知识
二次函数一般式为:
y=ax2+bx+c
顶点坐标:(
−b2a
,
4ac−b24a
)
二次函数
y=ax²+bx+c
=a(x+
b2a
)²+c-
b24a
(a≠0)
这里其实是跳步了,从前式转到后式,是用配方法转移的。
原式=a(
x2+bax
)+c
=a(
x2+bax+b24a2
)+c-
b24a
=
a(x+b2a)2+c−b24a
当a>0时二次函数图象开口向上,其有最小值
当x=-b/2a时
ymin=c−b24a=4ac−b²4a
当a<0时二次函数图象开口向下,其有最大值
当x=-b/2a时
ymax=c−b24a=4ac−b24a
x=−b2a
可以使y取得最大或最小值
(1)当a>0时,抛物线的开口向上,y有最小值.
(2)当a<0时,抛物线的开口向下,y有最大值.
将
x=−b2a
代入2次函数一般式即可求得y的极值(这是一般的做法)
另一种做法是配方法
把y表示成〔1〕
y=(kx+b)∗(kx+b)+h
或 〔2〕
y=−(kx+b)∗(kx+b)+h
当kx+b=0时,明显看出〔1〕取得最小值,〔2〕取得最大值
其实配方法的本质就是第一种做法
a>0时开口向上,有最小值,当
x=−b2a
时,取得最小值为
y=(4ac−b2)/4a
a<0时开口向下,有最大值,当
x=−b2a
时,取得最大值为
y=(4ac−b2)/4a
Attached CODE
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define fo(i,a,b) for (int i=a;i<=b;i++)
using namespace std;
double Profit_ans1,Profit_ans2,p,k;
int n;
double Calculation(int x,int y)
{
double p2=(double)(x+y-n)/(-k);
return ((double)y*(p2-p));
}
int main()
{
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
scanf("%d%lf%lf",&n,&p,&k);
fo(n1,0,n)
{
double P1=(double)(n-n1)/k;
double Profit=(double)(n1*(P1-p));
Profit_ans1=max(Profit_ans1,Profit);
double Tqy=(double)(P1-p);
int x=-Tqy/((double)(-1.0)/k*2.0);
double Lqy=Calculation(n1,x-1);
Lqy=max(Lqy,Calculation(n1,x));
Lqy=max(Lqy,Calculation(n1,x+1));
Profit+=Lqy;
Profit_ans2=max(Profit_ans2,Profit);
}
printf("%.3lf %.3lf",Profit_ans1,Profit_ans2);
return 0;
}