HDU 1576 A/B 解题报告 (求逆元)

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1576

这个题可以是乘法逆元的模板题,基本上只要理解了乘法逆元的求法和扩展欧几里得都能顺利写出来。

然而我一开始看了很多网上题解,都是推导之后再用扩展欧几里得,这个方法还是比较好想明白什么意思的。但是我一直不明白为啥这个题很多人说用求逆元做,冥思苦想之后(对我是才接触数论的小白)终于明白了。

其实我们首先要明白为啥会有求逆元这个东西,取模运算是个比较特殊的运算,比如:

(A * B) %  M  = (A % M  *  B % M) % M  这个式子是成立的,相对应的加法和减法都满足这个式子。但是除法不满足。所以我们在进行(A / B) % M  这种运算的时候,只能寻求其他的方法,这时候逆元就派上用场了。我们可以把前一个式子化成(A * B^-1 )% M 的形式,这样式子化为了(A % M * B^-1 % M) % M 的形式,这里的B^-1就是指的B关于M的乘法逆元。

那么具体怎么求出B关于M的乘法逆元呢?这时候扩展欧几里得就用上了。接下来先做几个形式变化。

对于 B * B^-1 ≡ 1 (mod M),我们设B^-1 等于x,根据同余式的性质,可以得到: Bx + My = 1  (y的符号换了相当于求的-y)。然后应用扩展欧几里得定理,可以求得使得等式成立的一个特解。然后让 x = (x % M + M) % M,这一步是为了去除x为负值的情况,如果x为负值,就求得最小正值,因为通解是X + k * M啊。

上一波C艹实现

#include 
#include 

using namespace std;
typedef long long LL;
const int MOD = 9973;

LL ex_gcd(LL a, LL b, LL &x, LL &y){
    if(b == 0){
        x = 1;
        y = 0;
        return a;
    }
    ex_gcd(b, a % b, x, y);
    int temp = x;
    x = y;
    y = temp - (a / b) * y;
}
int main()
{
    //freopen("input.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while(T--){
        LL n, b;
        scanf("%I64d %I64d", &n, &b);
        LL x, y;
        ex_gcd(b, MOD, x, y); 
        LL ans = (x * n % MOD + MOD)%MOD;
        printf("%I64d\n", ans);
    }
    return 0;
}

 

你可能感兴趣的:(HDU 1576 A/B 解题报告 (求逆元))