同余的意义
12 三等号 5(mod 7)
12 和 5 在除数相同时 余数相同
a b(mod ) c
m n (mod) c
a+m b+n (mod) c
(a(+||*)b)%c = (a%c+b%c)%c
(a-b)%c=((a%c-b%c)+c)%c
逆元:a×b=1(单位元)a,b互为逆元
幺元:代数系统中的度量 1×a=a 乘相当于没有乘
11 : 一个数对11求余 奇数位数减去,偶数位数加上
a(n)*10(n)+a(n-1)*10(n-1)
10 的 n次方 (11-1)(n个)%10相乘
费马小定理:(a的p-1次幂 对p求余) 等于 (1对p求余)(a和p互为素数)
贝祖等式:ax+by=gcd(a,b)=gcd(b,a%b);能写成这个 就有整数解
ax1+by1=bx2+(a%b)y2
ax1+by1=ay2+b(x2-(a/b)*y2)
x1=y2;
y1=x2-(a/b)*y2;
a|b 即为 a能整除 b
费马小定理
a^(p-1) ≡1 (mod p)
两边同除以a
a^(p-2) ≡1/a (mod p)
什么(,,• ₃ •,,),这可是数论,还敢写1/a
应该写a^(p-2) ≡ inv(a) (mod p)
所以inv(a) = a^(p-2) (mod p)
这个用快速幂求一下,复杂度O(logn)(ง •̀_•́)ง
LL pow_mod(LL a, LL b, LL p){//a的b次方求余p
LL ret = 1;
while(b){
if(b & 1) ret = (ret * a) % p;
a = (a * a) % p;
b >>= 1;
}
return ret;
}
LL Fermat(LL a, LL p){//费马求a关于b的逆元
return pow_mod(a, p-2, p);
}
方法二:
要用扩展欧几里德算法
还记得扩展欧几里德吗?(不记得的话,欧几里得会伤心的(╭ ̄3 ̄)╭♡)
a*x + b*y = 1
如果ab互质,有解
这个解的x就是a关于b的逆元
y就是b关于a的逆元
为什么呢?
你看,两边同时求余b
a*x % b + b*y % b = 1 % b
a*x % b = 1 % b
a*x = 1 (mod b)
你看你看,出现了!!!(/≥▽≤/)
所以x是a关于b的逆元
反之可证明y
附上代码:
#include<cstdio>
typedef long long LL;
void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){
if (!b) {d = a, x = 1, y = 0;}
else{
ex_gcd(b, a % b, y, x, d);
y -= x * (a / b);
}
}
LL inv(LL t, LL p){//如果不存在,返回-1
LL d, x, y;
ex_gcd(t, p, x, y, d);
return d == 1 ? (x % p + p) % p : -1;
}
int main(){
LL a, p;
while(~scanf("%lld%lld", &a, &p)){
printf("%lld\n", inv(a, p));
}
}
二:中国剩余定理:
模板:
#include<stdio.h>
#include <iostream>
using namespace std;
//扩展欧几里得算法
int exgcd(int a,int b,int &x,int &y)
{
int d;
if(b==0)
{
x=1;y=0;
return a;
}
d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
//中国剩余定理 ,r[]存放余数 ,prime[]存放两两互质的数
int Chinese_Remainder(int r[],int prime[],int len)
{
int i,d,x,y,m,n=1,sum=0;
//计算所以除数的积n,也是所以除数的最小公倍数
for(i=0;i<len;i++)
n*=prime[i];
//计算符合所以条件的数
for(i=0;i<len;i++)
{
m=n/prime[i];//计算除去本身的所有除数的积m
d=exgcd(prime[i],m,x,y);//计算w[i]*x+m*y=gcd(w[i],m)的一个解y
//累加整数解y的同并不断对n取余,其利用公式:(a+b)%c=(a%c+b%c)%c
sum=(sum+y*m*r[i])%n;
}
return (n+sum%n)%n;//满足所以方程的最小解
}
int main()
{
int n,i;
int prime[15],r[15];
while (printf("请输入组数n:\n"),scanf("%d",&n)!=EOF)
{
printf("请依次输入每组的除数和余数:\n");
for (i=0;i<n;i++)
{
scanf("%d%d",&prime[i],&r[i]);
}
//printf("%d\n",Chinese_Remainder(b,w,n));
printf("符合条件的最小整数:%d\n\n",Chinese_Remainder(r,prime,n));
}
return 0;
}
1.满足两两互质关系
LL china(int n, LL *a, LL *m)
{
LL M = 1, ret = 0;
for(int i = 0; i < n; i ++) M *= m[i];
for(int i = 0; i < n; i ++)
{
LL w = M / m[i];
ret = (ret + w * inv(w, m[i]) * a[i]) % M;
}
return (ret + M) % M;
}
2 不满足两两互质关系
typedef long long LL;
typedef pair<LL, LL> PLL;
PLL linear(LL A[], LL B[], LL M[], int n) //求解A[i]x = B[i] (mod M[i]),总共n个线性方程组
{
LL x = 0, m = 1;
for(int i = 0; i < n; i ++)
{
LL a = A[i] * m, b = B[i] - A[i]*x, d = gcd(M[i], a);
if(b % d != 0) return PLL(0, -1);//答案不存在,返回-1
LL t = b/d * inv(a/d, M[i]/d)%(M[i]/d);
x = x + m*t;
m *= M[i]/d;
}
x = (x % m + m ) % m;
return PLL(x, m);//返回的x就是答案,m是最后的lcm值
}