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

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

题目链接:P5656 【模板】二元一次不定方程 (exgcd)

题意:给定不定方程
a x + b y = c ax+by=c ax+by=c
若该方程无整数解,输出 − 1 -1 1
若该方程有整数解,且有正整数解,则输出其正整数解的数量,所有正整数解中 x x x 的最小值,所有正整数解中 y y y 的最小值,所有正整数解中 x x x 的最大值,以及所有正整数解中 y y y 的最大值。
若方程有整数解,但没有正整数解,你需要输出所有整数解 x x x 的最小正整数值, y y y 的最小正整数值。

正整数解即为 x , y x, y x,y 均为正整数的解, 0 \boldsymbol{0} 0 不是正整数
整数解即为 x , y x,y x,y 均为整数的解。
x x x 的最小正整数值即所有 x x x 为正整数的整数解中 x x x 的最小值, y y y 同理。

1 ≤ a , b , c ≤ 1 0 9 1\le a,b,c\le 10^9 1a,b,c109

根据裴蜀定理

对于 x , y x,y x,y 的二元一次不定方程 a x + b y = c ax+by=c ax+by=c ,其有解的充要条件为 gcd ⁡ ( a , b ) ∣ c \gcd(a,b) \mid c gcd(a,b)c

可知方程无解当且仅当 gcd ⁡ ( a , b ) ∤ c \gcd(a,b) \nmid c gcd(a,b)c

那么有解的时候,我们可以用扩展欧几里德算法求出一组特解

x ′ , y ′ x^{\prime},y^{\prime} x,y 满足
a x ′ + b y ′ = gcd ⁡ ( a , b ) ax^{\prime}+by^{\prime}=\gcd(a,b) ax+by=gcd(a,b)

考虑转化为原方程的一组特解。令 d = gcd ⁡ ( a , b ) d=\gcd(a,b) d=gcd(a,b)

则特解 x 0 = x ′ × c d , y 0 = y ′ × c d x_0=x^{\prime}\times \dfrac{c}{d},y_0 = y' \times \dfrac{c}{d} x0=x×dcy0=y×dc 满足
a x 0 + b y 0 = c ax_0 + by_0 = c ax0+by0=c
此时的 x 0 , y 0 x_0,y_0 x0,y0 就是一个平凡的解,考虑转化为更有价值的解

考虑增大 x 0 x_0 x0 x 0 + p x_0+p x0+p ,则 y 0 y_0 y0 需减小至 y 0 − q y_0-q y0q


{ a × ( x 0 + p ) + b × ( y 0 − q ) = c a x 0 + b y 0 = c \begin{cases} a\times(x_0+p)+b\times(y_0-q) = c\\\\ ax_0 + b y_0 = c \end{cases} a×(x0+p)+b×(y0q)=cax0+by0=c
可得 p = b q a p =\dfrac{bq}{a} p=abq

可以发现这样的解有无数个,我们只要找到一个最小正整数解即可(即 p , q ∈ Z + p,q\in \Z_+ p,qZ+ p , q p,q p,q 尽可能小)

∵ a ∣ b q , b ∣ b q \because a\mid bq,b\mid bq abq,bbq

∴ ( b q ) min ⁡ = lcm ⁡ ( a , b ) = a b gcd ⁡ ( a , b ) \therefore (bq)_{\min}=\operatorname{lcm}(a,b) = \dfrac{ab}{\gcd(a,b)} (bq)min=lcm(a,b)=gcd(a,b)ab


{ p min ⁡ = b d q min ⁡ = a d \begin{aligned}\begin{cases} p_{\min}&=\dfrac{b}{d}\\ \\ q_{\min}&=\dfrac{a}{d} \end{cases}\end{aligned} pminqmin=db=da
于是我们尝试将 x 0 x_0 x0 调至最小正整数( y 0 y_0 y0 同时也会改变 )

即找到一个最小的整数 k k k 使得 x 0 + k p ≥ 1 x_0 + kp \ge 1 x0+kp1


k = ⌈ 1 − x 0 p ⌉ k= \left\lceil{\dfrac{1-x_0}{p}}\right\rceil k=p1x0
然后将 x 0 x_0 x0 变为 x 0 + k p x_0 + kp x0+kp 即可,此时 y 0 y_0 y0 变化为 y 0 − q k y_0-qk y0qk

若此时 y 0 > 0 y_0 > 0 y0>0 ,则存在正整数解

  1. 正整数解的个数:使 y 0 y_0 y0 不停地减 q q q 就是所有可行正整数解,故答案为 ⌊ y 0 − 1 q ⌋ + 1 \left\lfloor{\dfrac{y_0-1}{q}}\right\rfloor+1 qy01+1

  2. x x x 的最小正整数值 x 0 x_0 x0

  3. y y y 的最小正整数值:使 y y y 不停地减 q q q ,最小的那个正整数就是答案,即 ( y 0 − 1 )   m o d   q + 1 (y_0-1)\bmod q + 1 (y01)modq+1

  4. x x x 的最大正整数值 y y y 最小时 x x x 最大

  5. y y y 的最大正整数值 y 0 y_0 y0

若此时 y 0 ≤ 0 y_0 \le 0 y00 ,则仅存在整数解

  1. x x x 的最小正整数值 x 0 x_0 x0
  2. y y y 的最小正整数值:构造 y 0 + k ′ q ≥ 1 y_0+k'q \ge 1 y0+kq1 ,易知 k ′ = ⌈ 1 − y 0 q ⌉ k^{\prime} = \left\lceil{\dfrac{1-y_0}{q}}\right\rceil k=q1y0 ,故答案为 y 0 + q × ⌈ 1 − y 0 q ⌉ y_0+q\times \left\lceil{\dfrac{1-y_0}{q}}\right\rceil y0+q×q1y0

据说要开 long long \text{long long} long long反正我#define int long long丝毫不慌(逃

主要代码如下(省略了快读和多组数据)

#define int long long
int exgcd(int a,int b,int &x,int &y)
{
    int d=a;
    if(!b)x=1,y=0;
    else d=exgcd(b,a%b,y,x),y-=a/b*x;
    return d;
}
void solve()
{
    int a,b,c,x,y;
    read(a);read(b);read(c);
    int d=exgcd(a,b,x,y);
    if(c%d!=0){puts("-1");return;}
    x*=c/d;y*=c/d;
    int p=b/d,q=a/d,k;
    k=ceil((1.0-x)/p),x+=p*k,y-=q*k;
    if(y>0)
    {
        write((y-1)/q+1);  pc(' ');
        write(x);          pc(' ');
        write((y-1)%q+1);  pc(' ');
        write(x+(y-1)/q*p);pc(' ');
        write(y);          pc(' ');
    }else
    {
        write(x);                       pc(' ');
        write(y+q*(int)ceil((1.0-y)/q));pc(' ');
    }
    pc('\n');
}

参考文献

[1] https://www.luogu.com.cn/blog/McHf/p5656-exgcd

转载请说明出处

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值