POJ 1061 (拓展欧几里得+求最小正整数解)

AC代码

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1e5+5;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
#define ls (i<<1)
#define rs (i<<1|1)
#define fi first
#define se second
#define mk make_pair
#define mem(a,b) memset(a,b,sizeof(a))
LL read()
{
    LL x=0,t=1;
    char ch;
    while(!isdigit(ch=getchar())) if(ch=='-') t=-1;
    while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
    return x*t;
}
LL gcd(LL a,LL b,LL &x,LL &y)
{
    LL res;
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    else res=gcd(b,a%b,x,y);
    LL x1=y;
    LL y1=x-a/b*y; //ax1+by1=bx2+a%b*y2=bx2+(a-a/b*b)y2=ay2+b(x2-a/b*y2);
    x=x1; y=y1;
    return res;
}
/*
 通解 x=x1+b/r*t , y=y1-a/r*t ,其中 t 为整数

  证明:
    将 x , y 带入方程得
    ax+ab/r*t+by-ab/r*t=c
    ax+by=c
    此等式恒成立

    得证

这里 b/r 与 a/r 为最小的系数,所以求得的解是最多最全面的
*/
LL exgcd(LL a,LL b,LL c,LL &x,LL &y)
{
    LL res=gcd(a,b,x,y);
    //printf("a=%lld b=%lld c=%lld gcd==%lld
",a,b,c,res);
    x*=c/res; y*=c/res; //之前求得的 ax0+by0=gcd 的情况 , 求出的 两边乘以 c/gcd ,x=x0*c/gcd,变为原式;
    b/=res; //最小周期;
    if(b<0) b=-b;// 可能存在gcd 为负数的情况
    x=(x%b+b)%b;//X=x0 +/- k*b/gcd; 通解的周期为 |b/gcd |,因此取余它;若b/gcd为负数,需要将符号加入±号里;
    return res;
}
int main()
{
    LL x=read(),y=read(),m=read(),n=read(),L=read();
    LL a=m-n,b=L,c=y-x,X,Y;
    LL tmp=exgcd(a,b,c,X,Y);
    if(c%tmp) printf("Impossible
");
    else printf("%lld
",X);
    return 0;
}
原文地址:https://www.cnblogs.com/DeepJay/p/12025189.html