扩欧——NKOJ P3677 观光车

问题描述  何老板带领n名游客来到一景区大门口,需要乘坐观光车游览景区。 景区提供两种观光车,一种是每辆车可以坐a名游客,包一辆车费用是p1块钱;另一种每辆车可以坐b名游客,包一辆车费用是p2块钱。 何老板想让这n名游客都坐上观光车,且每辆车都坐满。问何老板至少要花费多少钱?  输入格式 第一行,一个整数n,表示游客的总数。 第二行,两个空格间隔的整数,表示p1和a 第三行,两个空格间隔的整数,表示p2和b  输出格式 一行,一个整数,表示所需最少费用。 如果无解,输出“-1”
 样例输入 1  43 1 3 2 4  样例输出 1 15  样例输入 2 40 5 9 5 12  样例输出 2 -1  提示 样例1说明:第一种车13辆,第二种车1辆 1 <= n,a,b,p1,p2 <= 2,000,000,000
 
分析:
设第一种车、第二种车分别包x,y,辆
x*a+y*b=n;   
设 x1,y1 是满足上式的一组解 cost= (x1+t*dx)*p1+(y1-t*dy)*p2 =x1*p1+y1*p2+ (dx*p1-dy*p2)*t; 
是一个关于t的一次函数;记斜率为K=dx*p1-dy*p2 由于x,y>0,可以求出t的定义域:  x=x1+dx*t>=0  ==> t >= -x1/dx;  y=y1-dy*t>=0  ==> t <= y1/dy; 若  K<0 ,t=tmin=-x1/dx;     K>=0,t=tmax=y1/dy;
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>

#define LL long long
using namespace std;
LL n,p1,p2,a,b;

LL extend_gcd(LL a,LL b,LL &x,LL &y ){
	LL x0,y0,r;
	if(b==0){x=1;y=0; return a;}
	r=extend_gcd(b,a%b,x0,y0);
	x=y0;  y=x0-a/b*y0;
	return r;
}

int main(){
	LL gcd,x,y,mint,maxt,ans,dx,dy,k,t;
	cin>>n>>p1>>a>>p2>>b;
	gcd=extend_gcd(a,b,x,y);
	if(n%gcd!=0){
		cout<<-1; return 0;
	}
	x= x*n/gcd; y=y*n/gcd;
	ans= x*p1+y*p2;
	dx= b/gcd;	dy= a/gcd;
	k= (dx*p1-dy*p2);
	maxt= floor(((double) y)/dy);
	mint= ceil(((double) x)/ -dx);
	if(maxt<mint){
		cout<<"-1"; return 0;
	}
	else if(k>0) t=mint;
	else t=maxt;
	cout<<ans+k*t<<endl;
	//cout<<"k= "<<k<<" dx= "<<dx<<" dy="<<dy<<endl; 
	//cout<<"x= "<<x<<" y= "<<y<<" mint= "<<mint<<" maxt= "<<maxt<<endl;
}


你可能感兴趣的:(扩欧——NKOJ P3677 观光车)