乘法逆元
定义:对于任意的n>1,如果gcd(a,n)=1,那么方程ax=1(modn)对模n有唯一的解。
乘法逆元实例,比如计算(A/B)%K
其中K为常数,
当A特别大的时候侧需要乘法逆元。
定义:
满足a*k≡1 (mod p)的k值就是a关于p的乘法逆元。
为什么要有乘法逆元呢?
当我们要求(a/b) mod p的值,且a很大,无法直接求得a/b的值时,我们就要用到乘法逆元。
我们可以通过求b关于p的乘法逆元k,将a乘上k再模p,即(a*k) mod p。其结果与(a/b) mod p等价。
证:(其实很简单。。。)
根据b*k≡1 (mod p)有b*k=p*x+1。
k=(p*x+1)/b。
把k代入(a*k) mod p,得:
(a*(p*x+1)/b) mod p
=((a*p*x)/b+a/b) mod p
=[((a*p*x)/b) mod p +(a/b)] mod p
=[(p*(a*x)/b) mod p +(a/b)] mod p
//p*[(a*x)/b] mod p=0
所以原式等于:(a/b) mod p
例题,
Crawling in process... Crawling failed Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
Input
Output
Sample Input
Sample Output
void sovle()
{
long long a = 9973, b;
long long x, y;
long long c = 1;
long long T_case = 0;
cin >> T_case;
long long exgcd(long long a, long long b, long long &x, long long &y);
for (long long i = 0; i < T_case; i++)
{
long long n;
cin >> n >> b;
long long d = exgcd(b, -a, x, y);
if (abs(d) == 1)
{
long long k = n / d;
//long long p0 = x*k;
//long long q0 = y*k;
x = x*k;
long long t = 0;
//if (x<0)
//{
// t = -x;
// t = t%k;
// x = k - t; //或者不用t变量 直接x=k-(-x)%k;或者用while(x<0){x+=k/1;},不过不推荐使用,因为可能会超时!最好用 x=(x%k+k)%k即可,if语句也不用了;
//}
long long result;
result = x%a;
if (result < 0)
{
result = a + result;
}
printf("%lld\n", x);
printf("%lld",result);
/*for (long long t = 1; t < 10; t++)
{
cout << p0 + (b / d)*t << " " << q0 - (a / d)*t << endl;
}*/
}
else
{
cout << "sorry" << endl;
}
}
}
long long exgcd(long long a, long long b, long long &x, long long &y)//求解方程特解的过程中同时进行了求最大公约数的计算。//扩展欧几里得算法求解模线性方程
{
long long r;
if (b == 0)
{
x = 1;
y = 0;
return a;
}
else
{
r = exgcd(b, a%b, x, y);
long long t = x;
x = y;
y = t - (a / b)*y;
}
return r;
}
void Eratosthenes()
{
int vis[1000];
int n;
cin >> n;
memset(vis, 0, sizeof(vis));
for (int i = 2; i <=n ; i++)
{
for (int j = i * 2; j <= n; j += i)
vis[j] = 1;
}
for (int i = 0; i <= n; i++)
{
if (vis[i] == 0)
cout << i << endl;
}
}
总结:利用乘法逆元的求法,及其代换的相关公式,注意其中求得的余数有可能是负数此时就应当把辅助按照运算规律转换为正数。加油加油!!