HDU 1576 A/B(乘法逆元)

有关乘法逆元:


1,为什么要用乘法逆元。

假设有这么一种情况:你需要求 a/b % M 的值,但是由于a过大,所以你在算a的过程中不断地取模了,当然对于加减乘来说这样并不改变结果的正确性,但是。。。之后你又得除以b,这就很尴尬了,假如你没有取模之前算出来的 a = 1 000 000 008 ,b = 2,但是M = 1 000 000 007,所以取模之后为1,1/2 等于多少呢?0,对吧,但是这不对,正确性已经没有了,所以我们要通过某些方法求出b对M的逆元,对于上边这个例子来说,2对1 000 000 007的逆元为 500 000 004(设为x),所以求 a/b % M 就转变成 a * x 所以问题就解决了。


2,求乘法逆元的方法:

1)当M是素数时,且b与M互质时:

用费马小定理解决。费马小定理给出了这个式子:

bM11(modM)

简单变形:
bbM21(modM)

所以b对M的乘法逆元即为:
bM2

2)当b与M互质时:

可以用扩展欧几里得公式求得。
我们要求的即为下式中的x

bx1modM

简单变换:
bxmy=1

又因为在扩展欧几里得算法里对于形如
ax+by=gcd(a,b)=d
的这种式子,可以逆向把某些符合的x,y求出来。
所以用这个方法就可以求出下式中的x,即b的逆元。
bx+my=1

lli e_gcd(lli a,lli b,lli &x,lli &y){
    if(b == 0){
        x = 1;
        y = 0;
        return a;
    }
    lli ans = e_gcd(b,a%b,x,y);
    lli temp = x;
    x = y;
    y = temp - (a/b)*y;
    return ans;
}//最后的x即为所求,但因为有可能是负数,所以进行一部 x = (x % M + M) % M;

3,有关本题:

最终要求 答案 = A/B % 9973
告诉你 A % 9973 = n。
所以只要求出b对M = 9973 的逆元x,所以答案就是这个:

Ax(modM)=(Amodm)(xmodM)modM=nxmodM

其中
x=b1

#include <iostream>
#include <cstdio>

typedef long long int lli;
using namespace std;

lli e_gcd(lli a,lli b,lli &x,lli &y){
    if(b == 0){
        x = 1;
        y = 0;
        return a;
    }
    lli ans = e_gcd(b,a%b,x,y);
    lli temp = x;
    x = y;
    y = temp - (a/b)*y;
    return ans;
}

int main()
{
    int t;
    cin>>t;
    lli n,b;
    lli x,y;
    while(t--){
        scanf("%I64d%I64d",&n,&b);
        e_gcd(b,9973,x,y);
        x = (x%9973 + 9973) % 9973;
        printf("%I64d\n",x*n%9973);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值