【题解】P1023 税收与补贴问题
题面
前言
无聊的小学数学题
正文
一些小性质
相邻价位间销售量是线性变化的,由此可以推出没有直接给出销量的价位
eg. 样例中的 28 130 30 120
,由此可以计算出 \(29\) 时的销量应该是 \(125\),超过最高价位后的销量,一直推到小于 \(0\) 为止即可
数据一定可以整除,不然就没法做了
无聊的不等式
要求给定价位的利润最高,显然利润 \(ans=(单价+补贴) \times 销量\),也就是说对于任意价位,它的利润都不能大于给定价位的利润
eg. 样例中,对于价位 \(29\),我们需要满足 \((x+3)*110 \ge (x+2)*125\);对于价位 \(32\),需要满足 \((x+3)*110 \ge (x+4)*95\)
所有这样不等式的解集就是答案,取绝对值最小的就是答案
取整问题:正数应该向上取整,负数应该向下取整
手模样例……
-
读入期望价格,记为 \(r=31\)
-
读入
28 130
,用 \(d_i\) 表示价位 \(i\) 的销售量,则 \(d_{28}=130\) -
读入
30 120
,则 \(d_{30}=120\),并在 \([28,30]\) 之间递推,得到 -
以此类推……
-
读入
15
,则递推计算 \(d_{32}=95,d_{33}=80,...,d_{38}=5\),负数以后就不算了 -
对于价位 \(d_{28}=130\),解不等式 \((x+3) \times 110>=(x+0) \times 130\)
-
对于价位 \(d_{29}=125\),解不等式 \((x+3) \times 110>=(x+1) \times 125\)
-
重复循环直到结束,解出所有不等式得 \(4 \le x \le9\)
-
\(ans=4\)
代码
换个口味,不做阅读程序题力(详细注释版)
#include<iostream>
#include<cmath>
using namespace std;
const int maxn=1e5+10,inf=2147483647;
int x,m,n;
int p,d[maxn];//r代表成本价,x代表期望价格,d代表价位
int main(){
cin>>x>>m>>n;
int r=m;//记录成本价
while(true){
if(m==-1&&n==-1){
break;
}
d[m]=n;
for(int i=p+1;i<m;i++){
d[i]=d[i-1]+(n-d[p])/(m-p);//此处递推、未知价格销量,(n-d[p])/(m-p)是公差
}
p=m;
cin>>m>>n;
}
int dif=0;
cin>>dif;
while(d[p]>dif){
p++;
d[p]=d[p-1]-dif;//继续递推,递推完成后p就是d>0的范围
}
double mx=inf,mn=-inf;
for(int i=r;i<=p;i++){//从成本到p的递推
double ans=(d[x]*(x-r)-d[i]*(i-r))*1.0/(d[i]-d[x]);//求(x+d[i])*(i-r)<=(x+d[x_])+(x_-r)的通解,x是期望价格
double op=d[i]-d[x];//判断解的符号,g为正是小于,反之为大于。
if(op>0){
mx=min(mx,ans);//取所有"x<=..."中的最小值
}else{
mn=max(mn,ans);//取所有"x>=..."中的最大值
}
}
//此时[mn,mx]就是答案的范围,取绝对值最小的输出
if(mn>mx){
cout<<"NO SOLUTION"<<endl;
return 0;
}
if(mn>0){
cout<<ceil(mn)<<endl;//mx>mn>0,答案为mn上取整
}else if(mx<0){
cout<<floor(mx)<<endl;//mn<mx<0,答案为mx下取整
}else{
cout<<0<<endl;//mn<0<mx,显然是0绝对值最小
}
return 0;
}
后记
又双叒叕水过一篇题解
完结撒花!