HDU 1576扩展欧几里德(2013.10.20周赛D题)

Problem D

Time Limit : 1000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 8   Accepted Submission(s) : 7

Font: Times New Roman | Verdana | Georgia

Font Size: ← →

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
 
   

解决该题的关键是:

1、了解扩展欧几里德算法,可以运用其解出gcd(a,b)=ax1+by1中的x1、y1的值

2、由题可得以下内容:

n=A%9973,则n=A-A/9973*9973。又A/B=x,则A=Bx。所以Bx-A/9973*9973=n。即Bx-9973y=n。

到这里我们可以发现:只要求出x的值,即可算出x%9973,也就是(A/B)%9973了。顺利解决了!

3、题目关键转到如何求出x了。题目的输入是n和B,利用扩展欧几里德算法可求出gcd(B,9973)=Bx1+9973y1=1的x1。

等式两边同乘以n,得B(nx1)-9973(-ny1)=n。可知nx1就是Bx-9973y=n的解了!!!即x=nx1。

4、对于第三部得到的x可能是负数,由题这显然是不正确的。

可以做这样的转化:(x%9973+9973)%9973

 
   
扩展欧几里得算法终于还是要攻克了……现在是第一道题扩展欧几里得……多做下这个题目,找下这方面扩展欧几里德做才得了。
#include <iostream>
#include <map>
#include <deque>
#include <vector>
#include <queue>
#include <stack>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
int x,y;
void exgcd(int a,int b)
{
    if(b==0)
    {
        x=1;
        y=0;
        return;
    }
    else
    {
        exgcd(b,a%b);
        int t=x;
        x=y;
        y=t-a/b*y;
    }
}
int main()
{
    int n,b,t;
    cin>>t;
    while(t--)
    {
        cin>>n>>b;
        exgcd(b,9973);
        x*=n;
        int ans=(x%9973+9973)%9973;
        cout<<ans<<endl;
    }
    return 0;
}


你可能感兴趣的:(HDU 1576扩展欧几里德(2013.10.20周赛D题))