CH3301 exgcd

CH3301 exgcd

题面
CH3301题面

思路
很清楚了就是 a x ≡ 1 ( m o d   b ) ax\equiv 1(mod\space b) ax1(mod b),根据同余的定义,那么就有 a x − 1 ≡ 0 ( m o d   b ) ax-1 \equiv0(mod\space b) ax10(mod b),又可以得到 b ∣ a x − 1 b\mid ax-1 bax1,不妨令这个倍数为-y,对应的Eucild方程就是 ( a x + b y = 1 ) (ax+by=1) (ax+by=1)(如果等于号的右边不是1(假如是p),可以先通过exgcd算出等于号右边改为gcd的解,如果gcd不能整除p,该方程无解,有解时把解乘以p/gcd就是所求方程的解,很好理解吧(把等于gcd的方程两边乘上这个倍数,就能找到其与右边等于p的方程的解得关系了)),找到x的集合就行了,由于整除1的数只有1,那么只能 g c d ( a , b ) = 1 gcd(a,b) = 1 gcd(a,b)=1,用exgcd求出一个解 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),那么通解集合就是(尝试代入试一下,真的记不住) x = x 0 + k ∗ b ,   y = y 0 − k ∗ a   ( k ∈ Z ) x = x_0+k*b,\space y= y_0-k*a\space (k \in Z) x=x0+kb, y=y0ka (kZ) 也就是所有模b同余 x 0 x_0 x0的整数,通过取模操作把解得范围移动到1-b之间,就得到了最小正整数解

注意事项
1)把包括负数在内的数调到最小正整数范围的公式
a = ( ( a   m o d   b ) + b ) m o d   b (1) a = ((a\space mod\space b)+b)mod\space b \tag{1} a=((a mod b)+b)mod b(1)
2)exgcd()在递归过程中,由于使用的是传引用(这里等效于全局变量),先把这一层栈的结果赋给一个值(而不是直接return),然后依次改变x和y,然后再return,这种调用到最底层返回值,并在传值到最顶层(经过逐层运算)返回值的方法不常见,相当于一次顺便做了多次的递归,值得学习
3)这里输出的时候那个(long long)可以不加(是因为巧了),按理来说如果b取2e9,x又刚好大于2e8就超了

代码

#include <iostream>

using namespace std;
typedef long long ll;
int x,y;
int exgcd(int a,int b,int &x,int &y)
{
    if(!b) {x = 1;y = 0;return a;}
    else
    {
        int d = exgcd(b,a%b,x,y);
        int z = x;x = y;y = z-(a/b)*y;
        return d;
    }
}
int main()
{
    int a ,b;
    cin >>a >> b;
    int ans = exgcd(a,b,x,y);
    cout << (((ll)x%b)+b)%b<<endl;
    //eliminate the minus one
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值