P1032 税收与补贴问题
骚粉色继续了解一下。
久违的恶心的题目。是我在交叉模拟试炼场A的最后一道题,也是一直做不下去的题...
参考:
https://www.luogu.org/problemnew/solution/P1023?page=2
https://www.luogu.org/problemnew/solution/P1023
解不等式:
准确来说:就是解N个价格的不等式:
最后记住在开始的时候处理好所有价格和销售量,解不等式,求出MIN<=a<=MAX
还需要判断绝对值哪个大,选哪一个。
由于C取整的问题,>=3.2 ===取4而不是取3,取整会取到3 ;<=-1.2 ===取-2而不是-1,取整会取到-1
先上自己的代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#define FOR(a,b) for(register int i=a;i<=b;i++)
#define LL long long
#define ULL unsigned long long
using namespace std;
struct node
{
int price;
int number;
}A[100500];
int main()
{
int firstcost,firstsales;//成本和初始销售量
int ans,neededprice,needednum;//最后需要补贴数和控制的价格
int prex,prey,x,y,cnt=0;//x,y作为临时读取的变量,cnt用于记下来所有价格和销售量
double k;
int ansmin=-1000000,ansmax=1000000;
cin>>neededprice;
cin>>firstcost>>firstsales;
prex=firstcost,prey=firstsales;
A[++cnt].price=firstcost,A[cnt].number=firstsales;
while(x!=-1&&y!=-1)
{
cin>>x>>y;
if(x==-1&&y==-1)continue;
if(x>prex+1)
{
k=double(prey-y)/double(prex-x);
//cout<<"prey="<<prey<<endl;
//cout<<k<<endl;
for(int i=prex+1;i<x;i++)
{
A[++cnt].price=i;
A[cnt].number=prey+k*(i-prex);
}
}
A[++cnt].price=x,A[cnt].number=y;
prex=x,prey=y;
}
cin>>k;
x=A[cnt].price,y=A[cnt].number;
// cout<<x<<":"<<y<<endl;
for(int i=x+1;y-k*(i-x)>0;i++)
{
A[++cnt].price=i;
A[cnt].number=y-k*(i-x);
}
for(int i=1;i<=cnt;i++)
if(A[i].price==neededprice)
{
needednum=A[i].number;
break;
}
// cout<<needednum<<" "<<neededprice<<endl<<endl<<endl;
for(int i=1;i<=cnt;i++)
{
// cout<<A[i].price<<":"<<A[i].number<<endl;
double inf1;
double inf2;
int inf3;
if(needednum!=A[i].number)
{
inf1=double((A[i].price-firstcost)*A[i].number-(neededprice-firstcost)*needednum )/double(needednum-A[i].number);
inf2=((A[i].price-firstcost)*A[i].number-(neededprice-firstcost)*needednum )/(needednum-A[i].number);
if(needednum>A[i].number){/*cout<<">="<<endl;*/if(abs(inf1-inf2)>1e-6&&inf1>0)inf2++;}
else {/*cout<<"<="<<endl;*/if(inf1<0&&abs(inf1-inf2)>1e-6)inf2--;}
// cout<<inf1<<" "<<inf2<<endl;
inf3=(int)inf2;
}
if(needednum>A[i].number)
ansmin=max(ansmin,inf3);
else if(needednum<A[i].number)
ansmax=min(ansmax,inf3);
}
if(ansmax<=ansmin)
cout<<"NO SOLUTION"<<endl;
else
{
if(abs(ansmin)>abs(ansmax))
cout<<ansmax<<endl;
else cout<<ansmin<<endl;
}
}
大佬的代码://中间需要整理一下 我懒的弄了。
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define N 10050//这个题目的所有数据小于10000(但是上传题目的人居然没说,差评)
int main()
{
int pre,x,y,jian,m=1,tempp,tempn,i,k=0,kxy,min,max;
float umin = -1e9, umax = 1e9;
int price[N] = {0}, num[N] = {0};
scanf("%d", &pre);
scanf("%d%d",&x,&y);
price[m] = x; num[m] = y;
scanf("%d""%d",&x,&y);
while(x!=-1 && y!=-1){
if(x-price[m] == 1){
m++;
price[m] = x;
num[m] = y;
}
else{
kxy = -(num[m]-y)/(x-price[m]);//kxy为中间每差1元减少的销量
while(price[m] < x){
m++;
price[m] = price[m-1]+1;
num[m]=num[m-1]+kxy;
}
}//中间数据有空缺 scanf("%d%d",&x,&y);
}//循环读入数据并补充中间空缺的数据
scanf("%d",&jian);
tempn = num[m]; tempp = price[m];
while(tempn-jian > 0){
m++;
tempp++; price[m] = tempp;
tempn -= jian; num[m] = tempn;
}//不断增加售价直到销售量为0
for(i=1; i<=m; i++)
if(price[i] == pre){
k = i;
break;
}
if(k == 0){
printf("NO SOLUTION");
exit(0);
}//如果已知价格中没有政府预估价则输出"NO SOLUTION"并退出程序
for(i = 1; i < k; i++)
if ((float)((num[k]*(price[k]-price[1])-num[i]*(price[i]-price[1]))/(float)(num[i]-num[k]))<=umax)
umax=(float)(num[k]*(price[k]-price[1])-num[i]*(price[i]-price[1]))/(float)(num[i]-num[k]);
//(预估价的总利润-某价位上的总利润)/(某价位销量-预估价销量)=应该收的RMB
//这个地方不理解的话建议解一下上文列出的不等式
for(i = k+1; i <= m; i++)
if ((float)((num[i]*(price[i]-price[1])-num[k]*(price[k]-price[1]))/(float)(num[k]-num[i]))>=umin)
umin=(float)(num[i]*(price[i]-price[1])-num[k]*(price[k]-price[1]))/(float)(num[k]-num[i]);
//(某价位上的总利润-预估价的总利润)/(预估价销量-某价位销量)=应该补贴的RMB
if(umin>umax) printf("NO SOLUTION");//解集为空
else if(umin > 0){//需要补贴的情况
if(fabs(umin-(int)(umin))>1e-6) min=(int)(umin)+1;//float存在误差
else min=(int)(umin);
printf("%d",min);
}
else if(umax < 0){//需要收税的情况
if(fabs((int)(umax)-umax)>1e-6) max=(int)(umax)-1;//float存在误差
else max = (int)(umax);
printf("%d",max);
}
else printf("0");//若不需要补贴或收税
return 0;
}
解法二:
简单判断出,补贴和税收的影响显然是单方面变大或者变小,可以判断出,补贴变大,最高价格减少;税收变大,最高价格变大。
直接枚举补贴税收直到达成目标为止(前面的解法是解a,这个解法是枚举a)
#include<cstdio>
int exp,max,ans,pc,lc,ln,cnt,t=1,c,n,cc;
double k[100005],num[100005],kk,nn;
int main(){
scanf("%d",&exp);
scanf("%d%d",&c,&n); pc=c;
while(c!=-1&&n!=-1){
lc=c,ln=n,num[c]=n;
scanf("%d%d",&c,&n);
k[lc]=(n-ln)/(c-lc);//计算斜率
}
scanf("%d",&cnt);
for(int i=pc;i<=lc;++i)//处理出每一个价格的销售量
if(!num[i]) num[i]=kk*(i-cc)+nn;
else kk=k[i],cc=i,nn=num[i];
while(ln-cnt>0) lc++,ln-=cnt,num[lc]=ln;
for(int i=pc;i<=lc;++i) if((i-pc)*num[i]>max) ans=i,max=(i-pc)*num[i];//当不补贴或收税时计算出最大利润时的价格
if(ans==exp) puts("0");
else if(ans>exp){//枚举补贴
for(int x=1;;x++){
max=ans=0;
for(int i=pc;i<=lc;++i) if((i-pc+x)*num[i]>=max) ans=i,max=(i-pc+x)*num[i];
if(ans==exp){printf("%d",x);return 0;}
}
}
else{//枚举税收
for(int x=-1;;x--){
max=ans=0;
for(int i=pc+1;i<=lc;++i) if((i-pc+x)*num[i]>=max) ans=i,max=(i-pc+x)*num[i];
if(ans==exp){printf("%d",x);return 0;}
}
}
}
P1100 高低位交换
简单的模拟,但主要是有行代码简单到我觉得非常牛逼,要把它供出来。
参考:https://www.luogu.org/problemnew/solution/P1100
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
unsigned long long x;
cin>>x;
cout<<((x&0x0000ffff)<<16|(x&0xffff0000)>>16)<<endl;//万无一失的做法
}