P1032 税收与补贴问题 + P1100 高低位交换

P1032 税收与补贴问题

骚粉色继续了解一下。

久违的恶心的题目。是我在交叉模拟试炼场A的最后一道题,也是一直做不下去的题...

参考:

https://www.luogu.org/problemnew/solution/P1023?page=2

https://www.luogu.org/problemnew/solution/P1023

解法一:

解不等式:

准确来说:就是解N个价格的不等式:

(pri-firstcost+a)*num[pri]\geq \sum( price-firstcost+a)*num[price]

(num[pri]-num[price])*a>=(price-firstcost)*num[price]-(pri-firstcost)*num[pri]

最后记住在开始的时候处理好所有价格和销售量,解不等式,求出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;//万无一失的做法
}

猜你喜欢

转载自blog.csdn.net/mxYlulu/article/details/82590700