题解 P1292 【倒酒】

· · 题解

偷偷嘟囔几句:为啥因为排版丑拒我好几次,好委屈

楼上的大佬们讲了思路和代码
我在这里简单讲下欧几里得扩展欧几里得
开讲之前,先来说下必须知识

下面是当a>b>0时的证明(建议手模一遍,很简单):
a × x1+b × y2=gcd(a,b)
b × x2+(a%b) × y2=gcd(b,a%b)

由朴素的欧几里得算法得:
∵ gcd(a,b)=gcd(b,a%b)
∴ a × x1+b × y2=b × x2+(a%b) × y2

接下来用待定系数法,将等式右边变形为:
b × (x2-(a%b) × y2) + a × y2

就有了这个等式:
a × x1+b × y2=b × (x2-(a%b) × y2) + a × y2
那么,显然,对应项系数相等:
x1 = y2
y1 = (x2-(a%b) × y2)

综合上述证明,递归的式子已经很显然了
贴板子:

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

到这里,如果你认真的看完了,并且看懂了
尝试一下这个吧
P1082 同余方程

最后,我们来说这道题P1292 倒酒

对于第一问,因为a与b互质,如果来回倒酒,
那么酒的数量一定是a和b的公约数
又因为题目说是最小的酒量
那么自然就是最大公约数啦gcd(a,b)
那我exgcd不是白讲了??(小声bbbbb)
看数据范围,10^9
emmmm,假如酒馆老板非常抠,a和b全是特别小的杯子
妥妥的安排你去TLE
你万般无奈的回头仔细看了exgcd
并且极不情愿的把板子粘了下来
然后第一问结束了。。。

对于第二问呢,无非就是卡一个最小次数出来
本人认为@war1111
大佬讲的非常仔细,大家可以找找他的题解阅览
最后,泥谷的优良传统:高清无码

#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <cstring>
using namespace std;

inline int read(){
    int x=0,w=1;
    char ch=getchar();
    for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    return x*w;
}

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

int main(){
    int a,b,x,y;
    a=read(),b=read();
    int ans=exgcd(a,b,x,y);
    cout<<ans<<'\n';
    x*=-1,a*=-1;
    while(x<0||y<0){
        x+=b/ans*(x<0);
        y-=a/ans*(x>=0);
    }
    cout<<x<<" "<<y;
    return 0;
}

希望能给初学者良好的基本知识,顺手留赞(~不要脸的逃了QAQ~)