【拓展欧几里得】渡河(2022.5.21)

上题目!

题目

2.1 题目描述

现在有 N 名游客需要渡河到对岸,但是岛上只有两艘船,第一艘船可以容纳 n1 名游客,第二艘船可以容纳 n2 名游客,为了不浪费位置,船长要求每次必须坐满才能出发。现在已知使用第一艘船运输一趟需要花费 c1,使用第二艘船运输一趟需要花费 c2,问最小总花费。

2.2 输入格式

第一行为一个整数 T,表示数据组数;
接下来T 行,每行五个整数 N, n1, c1, n2, c2,含义如题意所述。

2.3 输出格式

输出T 行对应T 组数据的答案,每行输出两个整数m1 和 m2 分别表示总花费最小时第
一艘船和第二艘船的运输趟数,若无解则输出“No solution”。当有解时,保证最优解唯一。

2.4 样例输入

2 
43 3 1 4 2 
40 9 5 12 5 

2.5 样例输出

13 1 
No solution 

2.6 数据范围与约定

对于前30%的数据 N≤100;
对于100%的数据,1≤T≤10000,1≤N,c1,c2,n1,n2≤2*109。

解思

拓欧跑一遍求最优通解(x,y大于零且价值最大的船对应的次数最大)即可

上代码

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
	int f=1,j=0;char w=getchar();
	while(w>'9'||w<'0'){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(w>='0'&&w<='9'){
		j=(j<<3)+(j<<1)+w-'0';
		w=getchar();
	}
	return f*j;
}
int t;
int extend_gcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1;y=0;
		return a;
	}
	int d=extend_gcd(b,a%b,x,y);
	int tmp=x;
	x=y;
	y=tmp-(a/b)*y;
	return d;
}
int n,x,y,c1,c2,a,b;
signed main(){
	//freopen("river.in","r",stdin);
	//freopen("river.out","w",stdout);
	t=read();
	while(t--){
		int use=0;
		n=read();a=read();c1=read();b=read();c2=read();
		if(a*c2<=b*c1)swap(a,b),use=1;
		int d=extend_gcd(a,b,x,y);
		if(n%d!=0){
			printf("No solution\n");
			continue;
		}
		x*=n/d;y*=n/d;
		int tag=a/d,k;
		if(y<0){
			k=abs(y)/tag;
			if(y+k*tag<0)k++;
			y+=tag*k;
			x-=tag*b/a*k;
		}
		else{
			k=y/tag;
			y-=tag*k;
			x+=tag*b/a*k;
		}
		if(x<0||y<0)printf("No solution\n");
		else if(!use)printf("%lld %lld\n",x,y);
		else printf("%lld %lld\n",y,x);
	}
	return 0;
}
/*
2
43 3 1 4 2
40 9 5 12 5
1
1 5 1000 7 1
*/
posted @   flywatre  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示