hdu_1576A/B(扩展欧几里得求逆元)

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

A/B

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4020    Accepted Submission(s): 3091


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
 

 

Author
xhd
 

 

Source

题解:

直接算数B的逆元然后乘n就是结果了。呵呵呵

逆元:

  定义:B 的逆元x满足Bx===1(mod m);

  可以写成Bx+ym === 1(mod m);

  所以可以用扩展欧几里得算出x和y(注意。这里必须要求B和m 是互质的才有结果)

  但是注意到这个题中的M很特殊,是一个质数,所以可以用费马小定理来求逆元

费马小定理说,对于素数 M 任意不是 M 的倍数的 b,都有:

b ^ (M-1) = 1 (mod M)

于是可以拆成:

b * b ^ (M-2) = 1 (mod M)

于是:

a / b = a / b * (b * b ^ (M-2)) = a * (b ^ (M-2)) (mod M)

也就是说我们要求的逆元就是 b ^ (M-2) (mod M)

 

 1 //求乘法逆元,扩展欧几里得,或者是费马小定理
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int pow(int b,int n)
 7 {
 8     int ans = 1;
 9     for(int i = 0; i < n; i++)
10     {
11         ans = (ans*b)%9973;
12     }
13     return ans;
14 }
15 int main()
16 {
17     int T;
18     scanf("%d",&T);
19     while(T--)
20     {
21         int n,b;
22         scanf("%d%d",&n,&b);
23         b = b%9973;
24         int tm = pow(b,9971);
25         int sol = (n*tm)%9973;
26         printf("%d\n",sol);
27     }
28     return 0;
29 }

 

posted on 2016-07-15 07:13  若流芳千古  阅读(203)  评论(0编辑  收藏  举报

导航