求
AB(mod9973)
已知
gcd(B,9973)=1
,所以
AB(mod9973)=A∗B−1(mod9973)
,重在求乘法逆元:
由于
(B,9973)=1
,利用
Fermat
小定理最简单,逆元即为
Bmod−2
AC代码:
/**************************************************************
* By: Xingxing
* Date: 2016-09-26
* Address: http://blog.csdn.net/legend_pawn?viewmode=contents
**************************************************************/
#include <iostream>
#include <cstdio>
typedef long long ll;
const int mod=9973;
using namespace std;
ll quickpow(ll a,ll b){
int res=1;
while(b>0){
if(b&1)
res=res*a%mod;
b=b>>1;
a=(a%mod)*(a%mod)%mod;
}
return res;
}
int main(){
//freopen("input.txt","r",stdin);
int T;
cin>>T;
while(T--){
int n,b;
scanf("%d%d",&n,&b);
ll ans;
ans=n*quickpow(b,9971)%mod;
cout<<ans<<endl;
}
return 0;
}
另一种方法是扩展欧几里得求乘法逆元,即求解不定方程 b−1∗b+9973y=1
AC代码:
/**************************************************************
* By: Xingxing
* Date: 2016-09-26
* Address: http://blog.csdn.net/legend_pawn?viewmode=contents
**************************************************************/
#include <iostream>
#include <cstdio>
typedef long long ll;
const int MOD=9973;
using namespace std;
ll extend_gcd(ll a,ll b,ll &x,ll &y){
if(a==0 &&b==0)
return -1;
if(b==0){
x=1;y=0;return a;
}
ll d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
ll mod_reserve(ll a){
ll x,y;
ll d=extend_gcd(a,MOD,x,y);
if(d==1)
return (x+MOD)%MOD;
else
return -1;
}
int main(){
//freopen("input.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
int n,b;
scanf("%d%d",&n,&b);
ll ans;
ans=(n*(mod_reserve(b)%MOD))%MOD;
cout<<ans<<endl;
}
return 0;
}
最后一种:
要求 求
1,2,⋯,p−1modp
的逆元,然后就看到了一个
O(n)
的做法
这个做法实际上是这样的,首先
1−1≡1 (mod p)
然后我们设:
p=k∗i+r,r<i,1<i<p
再将这个算式放到
modp
的意义下得到:
k∗r+i≡0 (mod p)
两边同时乘上 i−1,r−1就会得到
k∗r−1+i−1≡0 (mod p)i−1≡−k∗r−1 (mod p)i−1≡−⌊pi⌋∗p (mod i) (mod p)
代码:
A[i] = -(p / i) * A[p % i];