hdu 1573 A/B (擴展歐幾里得)

Problem 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

 /*************************

歐幾里得算法,又稱輾轉相除法,用於求最大公約數:  c = gcd(a,b) = gcd(b,a%b);

擴展歐幾里得算法:

若a,b不全爲0,則存在x,y使得 c = gcd(a,b) = a*x+b*y;   

因爲 gcd(a,b) = gcd(b,a%b),則有 x*a + y * b = x1 * b + y1 * (a%b),等式右邊變形,則得到:b * x1 + (a%b) * y1 = b * x1+(a-a/b*b) * y1 = a * y1+b * (x1 - ( a / b) * y1)。

則  x = y1 , y= x1-(a/b)*y1,然後可由後向前迭代得到 x,y。

  

1573 A/B:

 A%B = 0 可令 x = A / B -> A = B*x;

n = A % 9973 = A - A / 9973 * 9973 : 

 = B*x - A/9973*9973

 = n

可以 令 y = A / 9973;  則 B * x + y * 9973 = n;    

因爲 gcd(9973,B) = 1,所以不能用exgcd(B,9973,x,y);

B * x1 + 9973 * y1 = 1; -> B * x1 *n + 9973 * y1 * n = n;

紅色字體的兩個式子比較係數就可以看出 x = x1 * n;

然後求 x % 9973 就OK 了

代碼:

#include <iostream>
using namespace std;
int exgcd(int a,int b,int &x,int &y)//  擴展歐幾里得函數模板
{
    if(b==0)
    {
        x = 1;y = 0;return a;
    }
    int d = exgcd(b,a%b,x,y);
    int t = x;
    x = y;
    y = t-a/b*y;
    return d;
}

int main()
{
    int t,n,B,x,y,ans,xx;
    cin>>t;
    while(t--)
    {
        cin>>n>>B;
        ans = exgcd(B,9973,x,y);
        xx = x*n;
        ans = (xx%9973+9973)%9973;  // 防止 x 爲負數
        cout<<ans<<endl;
    }
}




  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章