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

来源:互联网 发布:网络神书 编辑:程序博客网 时间:2024/06/06 02:45

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

21000 5387 123456789

Sample Output

79226060

解决该题的关键是:

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;}


原创粉丝点击