• Jams倒酒


    【题目描述】

    Jams有两种酒杯,容积分别为AmL、BmL,并且他只能在两种酒杯和一个酒桶之间反复倾倒,从而得到新的体积的酒。

    现规定:

    (1)A >= B;

    (2)酒桶容积无限;

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

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

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

    ③将容积为BmL的酒杯中的酒倒入容积为AmL的酒杯中;

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

    Jams希望倾倒若干次,使容积为AmL的酒杯中剩下的酒的体积尽可能小。

    【输入描述】

    输入两个整数A、B。

    【输出描述】

    第一行输出一个整数,表示能够得到的最小体积的酒;

    第二行输出两个整数PA、PB,分别表示用容积为AmL的酒杯倒酒的次数以及将酒倒入容积为BmL的酒杯的次数。

    如果有多组PA、PB满足要求,优先输出PA最小的那一组,如果当PA最小时,有多个PB满足要求,优先输出最小的PB。

    【样例输入】

    5 3

    【样例输出】

    1

    1 2

    【数据范围及提示】

    样例的倾倒方案为:

    (1)桶 --> B;

    (2)B --> A;

    (3)桶 --> B;

    (4)B --> A;

    (5)A --> 桶;

    (6)B --> A;

    对于20%的数据,PA+PB <= 5;

    对于60%的数据,PA <= 108

    对于100%的数据,0 < B <= A <= 109

    源代码:
    
    #include<cstdio>
    #define LL long long
    LL A,B,X,Y,Min;
    LL GCD(LL t1,LL t2) //辗转相除法。
    {
        return t2?GCD(t2,t1%t2):t1;
    }
    void ExGCD(LL t1,LL t2) //拓展欧几里得算法。
    {
        if (!t2) //此时,形成了GCD(A,0)=A,原式变为Ax+By=A,则x=1,y=0。
        {
            X=1;
            Y=0;
            return;
        }
        else
        {
            ExGCD(t2,t1%t2);
            LL t=X;
            X=Y;
            Y=t-t1/t2*Y;
        }
    }
    int main()
    {
        scanf("%I64d%I64d",&A,&B);
        Min=GCD(A,B);
        A/=Min;
        B/=Min; //也算是优化。
        ExGCD(A,B);
        while (Y<0)
          Y+=A; //合法。
        X=(1-Y*B)/A; //根据方程式暴力强求。
        printf("%I64d
    %I64d %I64d",Min,-X,Y); //想一想,这样即为最小值。
        return 0;
    }
    
    /*
        很不错的一道NOIP阶段数论题。
        想一想会发现,不管怎么倒,计量单位都是GCD(A,B)的倍数,则可得出Min=GCD(A,B)。
        我拓欧还不会啊啊啊!
        拓展欧几里得定理:对于两个不全为0的整数A、B,必存在一组解x、y,使得Ax+By=GCD(A,B)。
        转换为算法易得:GCD(A,B)=GCD(B,A%B)=......
        且有:Ax+By=Bx+(A%B)y=......(每个式子中的x、y都不相同)
        进行转化,Bx+(A%B)y=Bx+[A-(A/B)B]y=Ay+B[x-(A/B)y],类似于上一层Ax+By的形式。
        可推出,对于递归层数之间的x、y关系为:
            ①x1=y2
            ②y1=x2-(A/B)y2
        回溯到最后,便可以得出对于Ax+By=GCD(A,B)的一组解。
        由此算法进行推广,对于一般的方程Ax+By=C,可得其一组解为:
            ①X=x(C/GCD(A,B))
            ②Y=y(C/GCD(A,B))
        还可推得,对于所有的解(T为任意整数):
            ①X=x+B/GCD(A,B)T
            ②Y=y-A/GCD(A,B)T
        此之谓拓展欧几里得算法。
    */
  • 相关阅读:
    为IIS站点启用SSL加密
    SQL Server Analysis Service身份验证
    安装规划服务器(PPS 2007)
    用SQL Server Compact Edition创建移动应用程序 【转载】
    在Web Service中使用Windows验证的方式
    巧用Excel去除数据表中的重复行
    如何动态切换报表中的图表类型
    使用链接维度
    如何配置订阅以使用 Web 同步(RMO 编程)【转载】
    如何对数据进行合并及分组
  • 原文地址:https://www.cnblogs.com/Ackermann/p/6000891.html
Copyright © 2020-2023  润新知