取模专题
有理数取质数余
求 \(\frac{a}{b}\bmod p\) 其中 \(p\) 为质数。
费马小定理
费马小定理 : \(a^{p-1}\equiv 1~ (\bmod p)\) 其中 \(p\) 为质数。
\(\frac{a}{b}\bmod p\)
\(=\frac{a}{b}\cdot b^{p-1}\bmod p\)
\(=a\cdot b^{p-2}\bmod p\)
扩展欧几里德 exgcd
求不定方程 \(ax+by=\gcd (a,b)\) 其中的一个解
解法:
假设已经求出一组数\(x2,y2\),满足:\(bx_2+(a \bmod b) y_2=\gcd(a,b)\)
那么:\(ax+by=bx_2+(a \bmod b) y_2\)
因为:\(a \bmod b = a−b\times\frac{a}{b}\)
所以: \(ax+by = bx_2+( a−b\times\frac{a}{b}) y_2\)
\(ax+by=bx_2+ay_2 - b\times\frac{a}{b}y_2\)
\(ax+by=ay_2 - b(x_2-\frac{a}{b}y_2)\)
可以求出其中一组解:\(x=y_2 ~ , ~ y=x_2-\frac{a}{b}y_2\)
辗转相除使最后总会\(a_n=gcd(a,b),b_n=0\)
所以最后一层辗转相除的\(x_n=1\)
void exgcd(int a,int b,int &x,int &y){
if(b==0){
x=1;
y=1;
return;
}
exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
}
乘法逆元
求 \(ax \bmod b=1\) 的最小整数解
实质就是 \(ax-bc=1\)
可转换成 \(ax+by=1\)
不难证明 \(\gcd(a,b)>1\) 时无解
直接套用扩展欧几里德
#include <bits/stdc++.h>
using namespace std;
int a,b,x,y;
void exgcd(int a,int b,int &x,int &y){
if(b==0){
x=1;
y=1;
return;
}
exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
}
int main(){
scanf("%d%d",&a,&b);
exgcd(a,b,x,y);
printf("%d",(x%b+b)%b);
return 0;
}
有理数取余
求 \(\frac{a}{b} \bmod c\)
实求 \(\frac{a}{b} \equiv x ~(\bmod c)\)
\(=a\times\frac{1}{b} \equiv x ~(\bmod c)\)
只要求出 \(\frac{1}{b} \bmod c\) 就能求出 \(x\)
设 \(by\equiv1 \bmod c\)
使用乘法逆元求出 \(x\)
#include <bits/stdc++.h>
using namespace std;
int a,b,c,x,y;
void exgcd(int a,int b,int &x,int &y){
if(b==0){
x=1;
y=1;
return;
}
exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
}
int main(){
scanf("%d%d%d",&a,&b,&c);
exgcd(b,c,x,y);
printf("%d",a*(x%c+c)%c);
return 0;
}