HDU 1576 A/B [扩展欧几里德]

Description

要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。

Input

数据的第一行是一个T,表示有T组数据。 
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。

Output

对应每组数据输出(A/B)%9973。

Sample Input

2
1000 53
87 123456789

Sample Output

7922
6060

先来了解一下何为‘扩展欧几里德定理’:扩展欧几里得算法是用已知a,b求解一组x,y,使他们满足贝祖等式:ax+by=gcd(a,b)=d

题解: (1)由题可知:读入的是n和B,且gcd(B,9973) = 1 ;

           (2)假设(A/B)%9973 = k ; 所以 A/B = k + 9973*x  ---> A = Bk + Bx*9973 ;

                       且n = A % 9973 ;替换可得 : n = (Bk +Bx*9973)%9973

             (3)化简上式,因为是9973的倍数,所以取余为0 , 得: Bk % 9973  = n ; 

             (4)同(2)一样, 化简(3)式 , Bk = n + 9973* y  ;两边同除n并且移相可得 ---> Bk/n-9973*y/n = 1 ;

             (5)其符合  (k/n)*B - (y/n)*9973 = gcd(B,9973) = 1 ; 

                       故求解所得 x , y 即为 x = (k/n) , y = -(y/n);(此处y因为前面定义问题冲突,并不是一个y);

AC代码:

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long

using namespace std ;
void extend_gcd(ll a , ll b , ll &x , ll &y)
{
    if(b==0)
    {
        x = 1 ;
        y = 0 ;
        return ;
    }

    extend_gcd(b,a%b,x,y);
    int r = x;
    x = y ;
    y = r - (a/b)*y;
}
int main()
{
    ll a , b , n , t ;
    cin>>t;
    while(t--)
    {
        ll x , y ;
        cin>>n>>b;
        extend_gcd(b,9973,x,y);
        x = (x%9973+9973)%9973;//*此处的加是防止答案出现负数,加一层取余不影响结果;
        cout<<(x*n)%9973<<endl;
    }
    return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kelisita

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值