Modular Inverse
The modular modular multiplicative inverse of an integer a modulo m is an integer x such that a-1≡x (mod m)
. This is equivalent to ax≡1 (mod m)
.
Input
There are multiple test cases. The first line of input is an integer T ≈ 2000 indicating the number of test cases.
Each test case contains two integers 0 < a ≤ 1000 and 0 < m ≤ 1000.
OutputFor each test case, output the smallest positive x. If such x doesn't exist, output "Not Exist".
Sample Input3 3 11 4 12 5 13Sample Output
4 Not Exist 8
References
题意:求逆元
思路:更新一下这个博客,这道题用扩展欧几里得和欧拉定理求快速幂本质没有区别,都是可以的,当时比赛我用的欧拉定理快速幂求逆元不过,我以为是时间问题,但其实是被一个地方坑了,我最后快速幂取模后的答案又取了模,这样就会存在一种情况,这个数的逆元恰好就是m,而我们要求最小的正整数解,所以如果这里再取模就成0了就不是正数了,导致了答案错误,所以这里如果使用快速幂求逆元的话要么最后返回答案的时候不要再取模,要么函数出来后再判断一下。
扩展欧几里得code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int e_gcd(int a,int b,int &x,int &y){
if(b == 0){
x = 1;
y = 0;
return a;
}
int ans = e_gcd(b,a%b,y,x);
y -= a / b * x;
return ans;
}
int main(){
int t;
while(~scanf("%d",&t)){
while(t--){
int a,m;
int x,y;
scanf("%d%d",&a,&m);
int gcd = e_gcd(a,m,x,y);
if(gcd != 1){
printf("Not Exist\n");
continue;
}
int ans = x;
ans = ans % m;
if(ans <= 0) ans = ans + m;//这里千万不要再模m,万一答案是0,模完还是0
printf("%d\n",ans);
}
}
return 0;
}
欧拉定理code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int euler[1100];
void init(){
euler[1] = 1;
for(int i = 2; i < 1100; i++){
euler[i] = i;
}
for(int i = 2; i < 1100; i++){
if(euler[i] == i){
for(int j = i; j < 1100; j += i){
euler[j] = euler[j] / i * (i - 1);
}
}
}
}
int gcd(int a,int b){
if(b == 0)
return a;
else
return gcd(b,a%b);
}
int q_pow(int a,int b,int m){
int ans = 1;
while(b){
if(b & 1)
ans = ans * a % m;
b >>= 1;
a = a * a % m;
}
return ans % m;
}
int main(){
init();
int t;
scanf("%d",&t);
while(t--){
int a,m;
scanf("%d%d",&a,&m);
if(gcd(a,m) != 1){
printf("Not Exist\n");
}
else{
int ans = q_pow(a,euler[m]-1,m);
if(ans <= 0) ans += m;//注意这里的判断,被坑在这里了
printf("%d\n",ans);
}
}
return 0;
}