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

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


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
 

 

题意:给出A%9973和B的值,求(A/B)%9973。
解析:(A  /  B) % p = (A * inv(B) ) % p = (A % p * inv(B) % p) % p,其中p为模数9973, inv(B)为B关于模p的逆元。
 
同余式:
如果两个正整数a和b之差能被n整除,那么我们就说a和b对模n同余,记作:a≡b (mod n)。 
a≡b(mod n)等价于a与b分别用n去除,余数相同。
 
乘法逆元:
如果ax≡1 (mod p),且gcd(a,p)=1a与p互质,此为一个数有逆元的充要条件,此时逆元唯一存在),则称a关于模p的乘法逆元为x。
逆元的含义:模n意义下,1个数a如果有逆元x,那么除以a相当于乘以x。
 
求解逆元的方法:
1. 扩展欧几里得算法:
已知整数a、b,扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足贝祖等式ax + by = gcd(a, b)。
当a关于模b的逆元存在,有gcd(a, b) == 1,即扩展欧几里得算法可求得x, y满足ax + by = 1, 两边同时余b,
ax % b + by % b = 1 % b 
ax % b = 1 % b
ax ≡ 1(mod b)
所以x是a的模b乘法逆元,同理y是b的模a乘法逆元
算法时间复杂度:O(logn)
模板代码:
 1 int ex_gcd(int a, int b, int &x, int &y) {  // 函数返回gcd(a, b)
 2     if (b == 0) {
 3         x = 1, y = 0;
 4         return a;
 5     }
 6     int r = ex_gcd(b, a % b, y, x);
 7     y -= (a / b) * x;
 8     return r;
 9 }
10 
11 int main() {
12     int a, b, x, y;
13     cin >> a >> b;  // 求a关于模b的逆元
14     cout << (ex_gcd(a, b, x, y) == 1 ? (x % b + b) % b : -1) << endl;  // -1表示逆元不存在
15 
16     return 0;
17 }
View Code

 

2. 费马小定理:

内容:假如a是一个整数,p是一个质数,那么a- a是p的倍数,可以表示为

ap ≡ a (mod p)

如果a不是p的倍数(即gcd(a, p) == 1),这个定理也可以写成

ap-1 ≡ 1 (mod p)

变形得a * ap-2 ≡ 1 (mod p),所以a关于模p的逆元x = ap-2 (mod p),用快速幂模可快速求之。

算法时间复杂度:O(logn)

模板代码:

 1 LL pow_mod(LL a, LL b, LL p) {    //a的b次方取模p 
 2     LL ret = 1;
 3     while (b) {
 4         if(b & 1) ret = (ret * a) % p;
 5         a = (a * a) % p;
 6         b >>= 1;
 7     }
 8     return ret;
 9 }
10 LL Fermat(LL a, LL p) {   //费马小定理求a关于b的逆元 
11         return pow_mod(a, p-2, p);
12 }
View Code

相关文章: