洛谷 P1292 倒酒

Posted 小时のblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P1292 倒酒相关的知识,希望对你有一定的参考价值。

题目描述

Winy是一家酒吧的老板,他的酒吧提供两种体积的啤酒,a ml和b ml,分别使用容积为a ml和b ml的酒杯来装载。

酒吧的生意并不好。Winy发现酒鬼们都非常穷。有时,他们会因为负担不起aml或者bml啤酒的消费,而不得不离去。因此,Winy决定出售第三种体积的啤酒(较小体积的啤酒)。

Winy只有两种杯子,容积分别为a ml和b ml,而且啤酒杯是没有刻度的。他只能通过两种杯子和酒桶间的互相倾倒来得到新的体积的酒。

为了简化倒酒的步骤,Winy规定:

(1)a≥b;

(2)酒桶容积无限大,酒桶中酒的体积也是无限大(但远小于桶的容积);

(3)只包含三种可能的倒酒操作:

①将酒桶中的酒倒入容积为b ml的酒杯中;

②将容积为a ml的酒杯中的酒倒入酒桶;

③将容积为b ml的酒杯中的酒倒入容积为a ml的酒杯中。

(4)每次倒酒必须把杯子倒满或把被倾倒的杯子倒空。

Winy希望通过若干次倾倒得到容积为a ml酒杯中剩下的酒的体积尽可能小,他请求你帮助他设计倾倒的方案

输入输出格式

输入格式:

 

两个整数a和b(0<b≤a≤10^9)

 

输出格式:

 

第一行一个整数c,表示可以得到的酒的最小体积。

第二行两个整数Pa和Pb(中间用一个空格分隔),分别表示从体积为a ml的酒杯中倒出酒的次数和将酒倒入体积为b ml的酒杯中的次数。

若有多种可能的Pa、Pb满足要求,那么请输出Pa最小的一个。若在Pa最小的情况下,有多个Pb满足要求,请输出Pb最小的一个。

 

输入输出样例

输入样例#1:
5 3
输出样例#1:
1
1 2

说明

样例解释:倾倒的方案为:

1、桶->B杯;2、B杯->A杯;

3、桶->B杯;4、B杯->A杯;

5、A杯->桶; 6、B杯->A杯;

 

题解: 扩展欧几里得

a中酒全部到点就相当于对a取模了..然后假设倒入b中y次,则。

by≡?(mod a),要求的就是最小的?,显然?就是gcd(a,b)。因为

ax+by=?,?最小就是gcd(a,b)喽。然后扩展欧几里得就好了...

一开始50,在最小解上花费了很长时间..

代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int a,b,x,y,r;

int exgcd(int a,int b,int &x,int &y){
    if(b==0){
        x=1;y=0;
        return a;
    }
    int t,r=exgcd(b,a%b,x,y);
    t=x;x=y;y=t-a/b*y;
    return r;
}

int main(){
    scanf("%d%d",&a,&b);
    r=exgcd(a,b,x,y);
    x*=-1;a*=-1;
    while(x<0||y<0){
        x+=b/r;y-=a/r*(x>=0);
    }
    printf("%d\n",r);
    printf("%d %d",x,y);
    return 0;
}

 

以上是关于洛谷 P1292 倒酒的主要内容,如果未能解决你的问题,请参考以下文章

P1292 倒酒

p1292监狱(动态规划)

Jams倒酒(pour)

Jams倒酒

NOIP2016模拟赛Jams 倒酒(pour) - 扩展欧几里得

IO多路复用