拓展欧几里得|求逆元
逆元定义:如果一个线性同余方程 ax≡1 (mod b) ,则称x为a mod b 的逆元,记作a^−1
相当于求不定方程 ax+by=1 的解 (只要求gcd(a,b)=1,不要求b是质数)
ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b,x,y;
ll ex_gcd(ll a,ll b,ll &x,ll &y) {
if(b==0) {
x=1,y=0;
return a;
}
ll ans=ex_gcd(b,a%b,x,y);
ll t=x;
x=y;
y=t-a/b*y;
return ans;
}
ll inv(ll a,ll mod) {
ll g=ex_gcd(a,mod,x,y);
if(g!=1)return -1;//无解
return (x%mod+mod)%mod;
}
int main() {
cin>>a>>b;
cout<<inv(a,b);
}
递推求逆元
求,
对
取模的逆元。
(
,
)
于是有:
由于q一定小于i,所以可以递推。
ac代码:(简洁美观)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e6+10;
ll inv[N],a,b;
int main() {
scanf("%lld%lld",&a,&b);
inv[1]=1;
for(int i=2; i<=a; i++){
inv[i]=(b-(b/i)*inv[(b%i)]%b)%b;
}
for(int i=1;i<=a;i++){
printf("%lld\n",inv[i]);
}
}
中国剩余定理
给你n个如下的方程:
求解x
ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll n,a[N],r[N];
ll exgcd(ll a,ll b,ll &x,ll &y) {
if(b==0) {
x=1,y=0;
return a;
}
ll ans=exgcd(b,a%b,x,y);
ll t=x;
x=y;
y=t-a/b*y;
return ans;
}
ll CRT(int k, ll* a, ll* r) {
ll n = 1, ans = 0;
for (int i = 1; i <= k; i++) n = n * r[i];
for (int i = 1; i <= k; i++) {
ll m = n / r[i], b, y;
exgcd(m, r[i], b, y); // b * m mod r[i] = 1
ans = (ans + a[i] * m * b % n) % n;
}
return (ans % n + n) % n;
}
int main() {
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1; i<=n; i++){
cin>>a[i]>>r[i];
}
cout<<CRT(n,r,a)<<'\n';
}
BSGS
一种以的复杂度求解
的方法
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e8+10;
const int mod = 1e9+7;
ll p,b,n;
ll ksm(ll a,ll n){
ll ans=1;
while(n){
if(n&1)ans=ans*a%p;
a=a*a%p;
n>>=1;
}
return ans;
}
ll BSGS(ll a,ll b,ll p){
b=(b%p+p)%p;
if(b==1||p==1)return 0;
ll n=sqrt(p)+1;
unordered_map<ll,ll>m;
ll inva=ksm(ksm(a,n-1),p-2)*b%p;
for(ll i=n-1;~i;--i){
m[inva]=i;
inva=inva*a%p;
}
ll ta=1,powa=ksm(a,n);
for(ll k=0;k<=p;k+=n){
if(m.count(ta))return k+m[ta];
ta=ta*powa%p;
}
return -1;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>p>>b>>n;
ll ans=BSGS(b,n,p);
if(ans==-1)cout<<"no solution";
else cout<<ans;
}