1.求gcd
利用性质 gcd(a,b)=gcd(b,a%b)
int gcd(int a,int b) {
return b == 0 ? a : gcd(b,a%b);
} // 全正数
LL gcd(LL a,LL b)
{
if (a==0) return 1;
if(a<0) return gcd(-a,b);
while(b)
{
LL t=a%b;
a=b;
b=t;
}
return a;
} // 允许负数
2.快速幂
不再赘述
ll pow(ll a,ll b,ll mode) {
ll sum=1;
while (b) {
if (b&1) {
sum=(sum*a) % mode;
b--;
}
b/=2;
a=a*a%mode;
}
return sum;
}
3.扩展欧几里得
用于计算ax+by=gcd(a,b)的一组解
只要我们找到一组特殊的解 x0 和 y0,那么,我们就可以用 x0 和 y0 表示出整个不定方程的通解:
x = x0 + (b/gcd)*t
y = y0 – (a/gcd)*t
扩欧的具体操作是这样的
当前方程
ax+by=gcd
递归解的下一个方程
bx'+(a%b)y'=gcd
而 a%b = a - (a/b)*b
这样我们可以解得一个关系
x=f(x',y'),y=g(x',y')
然后递归回溯即可
扩欧的作用
可以计算出逆元
ax = 1(mod m)
这里,我们称 x 是 a 关于 m 的乘法逆元
可以等价于这样的表达式: a*x + m*y = 1,然后用扩欧就解决了
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 temp=x;
x=y;
y=temp-a/b*y;
return ans;
}
LL cal(LL a,LL b,LL c)
{
LL x,y;
LL gcd = ex_gcd(a,b,x,y);
if (c%gcd != 0) return -1;
x*=c/gcd;
b/=gcd;
if (b<0) b=-b;
LL ans=x%b;
if (ans<=0) ans+=b;
return ans;
}
void Testcal()
{
LL a,m;
scanf("%lld%lld",&a,&m); // ax mod m=1
LL x=cal(a,m,1);
cout<<x<<endl;
}
4.欧拉定理
欧拉定理的应用
1、欧拉降幂公式,非常重要
用这个公式降幂之后再配合快速幂加速取模过程
2、求逆元
当(a,n)=1即底数和模数互素的时候才可
5.欧拉定理的特例——费马小定理
1、若p是一个素数,那么对于任意一个整数a, a^p-a都是p的倍数,即a^p≡a(mod p)
感觉这条性质没啥用
2、若(a,p)=1,则 a^(p-1) ≡1(mod p)
当模数为素数而且底数和模数互素的时候才能用,用处:求逆元和降幂
6.求逆元的三个方法
ax=1(mod n)
1、扩展欧几里得,适用于一切情况
2、欧拉公式,适用于(a,n)=1
3、费马小定理,适用于(a,n)=1且n为素数
7.分解质因数(小数据)
int cnt[1000000];
void Divide(int N)
{
int n=N, i=1, p=0;
while (n!=0 && i<=tot)
{
p=0;
while (n%prime[i]==0) p++, n /= prime[i];
cnt[i]=p;
i++;
}
}
// 主函数中这样调用
Divide(2*3*5*7*11*13*13*13*19); // 分解质因数
8.中国剩余定理
问题
解法
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 temp=x;
x=y;
y=temp-a/b*y;
return ans;
}
LL China()
{
LL M=m[1], A=a[1], t,d,x,y;
int i;
for(i=2; i<=n; i++) {
d = ex_gcd(M,m[i],x,y); //解方程
if ((a[i]-A)%d!=0) return -1; //无解
x*=(a[i]-A)/d; t=m[i]/d; x=(x%t+t)%t; //求x
A=M*x+A; M=M/d*m[i]; A%=M; //模,防止爆
}
A=(A%M+M)%M;
return A;
}
void TestChina()
{
cin>>n;
for (int i=1; i<=n; i++) cin>>m[i]>>a[i];
LL x=China();
cout<<x<<endl;
}