HDU1576(扩展欧几里得算法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1576

题目大意:见题目

解题思路:开始的时候,看到求(A/B)%9973感觉像是直接利用同余公式即可解决,回顾一下同余公式:

(a+b)mod n = ((a mod n)+(b mod n))mod n

(a-b)mod n = ((a mod n)-(b mod n) + n) mod n

ab mod n = (a mod n)(b mod n) mod n

于是我就想,是不是可以利用其中的乘法公式进行计算呢,过程如下:

(A/B)%9973

=(A*(1/B))%9973          也就是把A/B看成是A和1/B的乘积

=((A%9973)*(1/B%9973))%9973

=(n*(1/B%9973))%9973              因为题目中给出n=A%9973

=(n/B)%9973                                 题目中限制1 <= B <= 10^9,因此1/B一定<9973,即1/B%9973==1/B


然后我就利用推出的这个公式进行计算,发现结果都是错的…………………………其实不难理解,公式化简到最后其实又变成了某两个数做除法再求模,但同余公式中明显没有针对除法的公式,因此这道题又一次告诉我们:没有针对除法的同余公式……………………切记切记



然后发现题目中给出了一个条件:gcd(B,9973) = 1,于是想到可以构造一个关于B和9973的等式,这样就可以利用扩展欧几里得算法解决了,推导如下:

设(A/B)%9973=k,所以A/B = 9973x+k

A = 9973Bx+kB

又因为A%9973=n

所以 (9973Bx+kB)%9973=n

所以kB%9973=n

kB = 9973y+n

kB-9973y=n

等式两边同时除以n可得:

B*k/n - 9973y/n = gcd(B,9973)=1

然后利用扩展欧几里得算法即可得到k/n的值,将其乘n可得k,为使结果>0则(k%9973+9973)%9973


AC代码:

#include <iostream>
using namespace std;
#define MOD 9973
void extend_gcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return ;
    }
    else
    {
        extend_gcd(b,a%b,y,x);
        y-=x*(a/b);
    }

}
int main()
{
    int x,y;
    int t;
    int n,b;
    cin>>t;
    while(t--)
    {
        cin>>n>>b;
        extend_gcd(b,MOD,x,y);
        x = (x%MOD+MOD)%MOD;
        cout<<(x*n)%MOD<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值