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)。
每组数据有两个数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 }