• 【中学高级本】倒酒


    P1659 - 【中学高级本】倒酒

    Description

    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酒杯中剩下的酒的体积尽可能小,他请求你帮助他设计倾倒的方案

    Input

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

    Output

    第一行一个整数c,表示可以得到的酒的最小体积。
    第二行两个整数Pa和Pb(中间用一个空格分隔),分别表示从体积为a ml的酒杯中倒出酒的次数和将酒倒入体积为b ml的酒杯中的次数。
    若有多种可能的Pa、Pb满足要求,那么请输出Pa最小的一个。若在Pa最小的情况下,有多个Pb满足要求,请输出Pb最小的一个。

    Sample Input

    5 3

    Sample Output

    1
    1 2

    Hint

    样例提示:
    倾倒的方案为:
    1、桶->B杯; 2、B杯->A杯;
    3、桶->B杯; 4、B杯->A杯;
    5、A杯->桶; 6、B杯->A杯;

    可以找出规律,A杯里的最小值为gcd(a,b),然后我就把a,b约分后模拟,然后TLE,居然还只T了一个点。
    往扩展欧几里得方面想,列出方程:b*pb-a*pa=1.然后我就扩展欧几里得求,然后调了将近一个小时。
    原因还是我不理解这个算法的原理。   智商捉鸡
    虽然papb都要求,但是是要保证a1最小。所以就可以只求pa,然后再带进去算pb
    然后是负数的问题不太好搞,所以原方程可以变成
    a*pa+b*pb=-1,这里把pb变了个号,
    但是这是不会影响答案的,因为你求的又不是
    pb,pb=-pb就好了

     1 #include<set>
     2 #include<map>
     3 #include<queue>
     4 #include<stack>
     5 #include<ctime>
     6 #include<cmath>
     7 #include<string>
     8 #include<vector>
     9 #include<cstdio>
    10 #include<cstdlib>
    11 #include<cstring>
    12 #include<iostream>
    13 #include<algorithm>
    14 #define LL long long
    15 using namespace std;
    16 void exgcd(LL &pa,LL &pb,LL a,LL b){
    17   if(b==0) pa=1,pb=0;
    18   else exgcd(pb,pa,b,(a+b)%b),pb-=pa*(a/b);
    19 }
    20 int main()
    21 {
    22   freopen("!.in","r",stdin);
    23   freopen("!.out","w",stdout);
    24   LL a,b;scanf("%lld%lld",&a,&b);
    25   if(a%b==0){printf("%lld
    ",b);printf("0 1");return 0;}
    26   else{
    27     int d=__gcd(a,b);
    28     a/=d;b/=d;
    29     printf("%d
    ",d);
    30     LL pa,pb;
    31     exgcd(pa,pb,a,b);
    32     pa*=-1;
    33     pa=(pa+b)%b;
    34     pb=(1+pa*a)/b;
    35     printf("%lld %lld",pa,pb);
    36   }
    37   return 0;
    38 }
    
    
    


  • 相关阅读:
    Linux命令:sed -i 解析、sed是什么、工作原理、基本语法使用、数字和正则定址、基本子命令以及最常用子命令 s 的用法
    【转】putty里面的连接key文件(ppk文件)转换为xshell里面使用的key文件
    【转】Go 中如何优雅关闭子进程?
    [转]golang 获取本机真实IP
    【转】prometheus数据写入TDengine
    怎么查看redhat的版本
    【转】YML是什么
    [转]为什么要进行URL编码
    [转]Ubuntu 上 Yarn 安装
    【转】docker -v 和Dockerfile 中VOLUME 区别
  • 原文地址:https://www.cnblogs.com/pantakill/p/6642192.html
Copyright © 2020-2023  润新知