1. 程式人生 > 實用技巧 >P5656 【模板】二元一次不定方程(exgcd)

P5656 【模板】二元一次不定方程(exgcd)

還不會 exgcd 的請移步窩的學習筆記,這裡只講怎麼搞出煩人的答案。

\(a,b\) 兩者互質的情況下,二元一次不定方程的通解:\(a(x+db)+b(y+da)=c\)

判定是否有解不多說,考慮有正整數解怎麼判。

對於未知數 \(x,y\),在其中一個滿足條件的同時我們希望另一個儘可能大。仔細觀察資料範圍,發現 \(a,b,c\) 均為正整數,也就是說隨著 \(x\) 的增大 \(y\) 會減小,那我們將一個取最小正整數解另一個算一下是否大於 \(0\) 即可。

然後很容易看出一個的最小正整數解就是另一個的最大正整數解。

記得開 long long,解記得乘上 \(c/\gcd(a,b)\)

時間複雜度 \(O(T\log a)\)~

code:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int x,y;
int read()
{
    int A;
    bool K;
    char C;
    C=A=K=0;
    while(C<'0'||C>'9')K|=C=='-',C=getchar();
    while(C>'/'&&C<':')A=(A<<3)+(A<<1)+(C^48),C=getchar();
    return(K?-A:A);
}
void exgcd(int a,int b)
{
    if(!a)
    {
        x=0;
        y=1;
        return;
    }
    int tmp;
    exgcd(b%a,a);
    tmp=y;
    y=x;
    x=tmp-b/a*x;
}
int gcd(int _,int __)
{
    return(!_?__:gcd(__%_,_));
}
void write(int X)
{
    if(X<0)putchar('-'),X=-X;
    if(X>9)write(X/10);
    putchar(X%10|48);
}
signed main()
{
    int t,a,b,c,k;
    t=read();
    while(t--)
    {
        a=read(),b=read(),c=read();
        k=gcd(a,b);
        if(c%k)
        {
            puts("-1");
            continue;
        }
        exgcd(a,b);
        c/=k;
        x*=c;
        y*=c;
        a/=k;
        b/=k;
        x=(!((x%b+b)%b)?b:(x%b+b)%b);
        y=(c-x*a)/b;
        if(y>0)
        {
            write((y-1)/a+1);
            putchar(' ');
            write(x);
            putchar(' ');
            y=(!(y%a)?a:y%a);
            write(y);
            putchar(' ');
            x=(c-y*b)/a;
            write(x);
            putchar(' ');
            write((c-(!(x%b)?b:x%b)*a)/b);
        }
        else
        {
            write(x);
            putchar(' ');
            write((!((y%a+a)%a)?a:(y%a+a)%a));
        }
        putchar('\n');
    }
    return 0;
}