学习笔记:快速幂、逆元
首先说一下取模的运算:
但是:
是错误的!!!等式不成立。
例如:
,
切入正题:逆元
, 就等于 吗,不一定,因为这里还有条件呢: p,所以在这个条件下 叫做 关于 的逆元,比如: ,那么 关于 的逆元就是 或者说 关于 的逆元就是 , 和 关于 互为逆元。
怎么求逆元呢?
费马小定理:
(
与
互质),
两边同时除
得:
,大功告成,
关于
的逆元就是
,记为
.
再回到刚开始的问题:如何求 ,应用刚才的费马小定理即转换为 再转化为 ,就完全转换成好算的乘法了,所以就求出 就可以算出结果了。
就可以用快速幂解决,复杂度
下面代码求
long long POW(long long a,long long b,long long mod)
{
long long base = a,ans=1;
while(b)
{
if(b&1)
ans=(ans*base)%mod;
base=(base*base)%mod;
b>>=1;
}
return ans;
}
再来个例题:hdu 1576 A/B
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
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<math.h>
using namespace std;
const int maxn=30010;
long long POW(long long a,long long b,long long mod)
{
long long base = a,ans=1;
while(b)
{
if(b&1)
ans=(ans*base)%mod;
base=(base*base)%mod;
b>>=1;
}
return ans;
}
int main()
{
int t;
cin>>t;
while(t--)
{
long long n,b;
cin>>n>>b;//n=A%mod
long long inv_b=POW(b,9973-2,9973);
long long ans=(n*inv_b)%9973;
printf("%lld\n",ans);
}
return 0;
}