同余

扩展欧几里得算法

扩展欧几里得算法,也叫 exgcd\text{exgcd}

时间复杂度为 O(log(a+b))O(\log(a+b))

long long exgcd(long long a,long long b,long long &x,long long &y){
    if(!b){
        x=1;y=0;
        return a;
    }
    long long d=exgcd(b,a%b,x,y);
    long long z=x;x=y;y=z-y*(a/b);
    return d;
}

使用时,提前定义变量 d,x0,y0d,x_0,y_0,调用 d=exgcd(a,b,x0,y0),程序执行完后 dd 就是最大公约数,x0,y0x_0,y_0 是方程 ax+by=gcd(a,b)ax+by=\gcd(a,b) 的一个解。

对于更为一般的方程 ax+by=cax+by=c,它有解当且仅当 dcd|c

乘法逆元

不是所有数都有逆元。

b,mb,m 互质,且 bab|a,则有整数 xx 使 a÷ba×x(modm)a\div b\equiv a\times x\pmod m,则 xxbb 的模 mm 乘法逆元。

利用费马小定理求乘法逆元

若保证 mm 为质数,则除数 bb 的模 mm 乘法逆元为 bm2b^{m-2}

需要用到快速幂

long long qni_fm(long long a,long long p){
    return qmi(a,p-2,p);
}

利用扩展欧几里得算法求乘法逆元

若保证 b,mb,m 互质,则除数 bb 的模 mm 乘法逆元可通过求解同余方程 b×x1(modm)b\times x\equiv1\pmod m

需要用到扩展欧几里得算法

long long qni_ol(long long a,long long p){
    long long x,y;
    exgcd(a,p,x,y);
    return x;
}

线性同余方程

a×xb(modm)a\times x\equiv b\pmod m 的解相当于求解 a×x+m×y=ba\times x+m\times y=b 的解,使用扩展欧几里得算法求解就可以了。

方程的通解是所有模 m÷gcd(a,m)m\div\gcd(a,m)xx 同余的整数。

中国剩余定理

中国剩余定理,也叫 CRT\text{CRT}

m1,m2,,mnm_1,m_2,…,m_n 两两互质,m=i=1nmim=\prod_{i=1}^nm_iMi=m÷miM_i=m\div m_itit_i 是线性同余方程 Miti1(modmi)M_it_i\equiv 1\pmod {m_i} 的一个解。对于任意 nn 个整数 a1,a2,,ana_1,a_2,…,a_n 的方程组

{xa1(modm1)xa2(modm2)              xan(modmn)\begin{cases}x\equiv a_1\pmod {m_1}\\x\equiv a_2\pmod {m_2}\\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \vdots\\x\equiv a_n\pmod {m_n}\end{cases}

有解,解为 x=i=1naiMitix=\sum_{i=1}^na_iM_it_i

long long CRT(int n,long long *a,long long *m){
    long long sum=0,M=1,x,y;
    for(int i=1;i<=n;i++)
        M*=m[i];
    for(int i=1;i<=n;i++){
        exgcd(M/m[i],m[i],x,y);
        sum+=a[i]*M/m[i]*x%M;
    }
    return (sum%M+M)%M;
}

时间复杂度为 O(nlog(a+b))O(n\log(a+b))

扩展中国剩余定理

扩展中国剩余定理,也叫 EXCRT\text{EXCRT}

若在中国剩余定理的基础上无法满足 m1,m2,,mnm_1,m_2,…,m_n 两两互质,则需要使用扩展中国剩余定理。

long long EXCRT(long long n,long long *a,long long *m){
	long long x,y,k,lcm=a[1],ans=m[1],d;
	bool f=1;
	for(int i=2;i<=n;i++){
		m[i]=(m[i]-ans%a[i]+a[i])%a[i];
		d=exgcd(lcm,a[i],x,y);
		if(m[i]%d)
			f=0;
		else
			k=x*(m[i]/d)%a[i];
		ans+=k*lcm;
		lcm=lcm/d*a[i];
		ans=(ans%lcm+lcm)%lcm;
	}
	if(f)
		return ans;
	return -1;
}

若无解会返回 1-1,时间复杂度仍是 O(nlog(a+b))O(n\log(a+b))

高次同余方程

BSGS算法

对于方程 axb(modp)a^x\equiv b\pmod p,可以采用 Baby Step,Giant Step\text{Baby Step,Giant Step} 算法,简称 BSGS\text{BSGS}

需要快速幂

无解返回 1-1,否则返回最小非负整数解。

时间复杂度为 O(p)O(\sqrt p)

long long Baby_Step_Giant_Step(long long a,long long b,long long p){
	map<long long,long long>hash;
	hash.clear();
    b%=p;
    long long t=(long long)sqrt(p)+1,val;
    for(long long j=0;j<t;j++){
    	val=(long long)b*qmi(a,j,p)%p; // b*a^j
		hash[val]=j;
	}
    a=qmi(a,t,p); // a^t
    if(!a)
        return b?-1:1;
    for(long long i=0;i<=t;i++){
    	val=qmi(a,i,p); // (a^t)^i
        long long j=hash.find(val)==hash.end()?-1:hash[val];
        if(j>=0&&i*t-j>=0)
            return i*t-j;
    }
    return -1;
}

back

posted @ 2021-08-18 18:01  luckydrawbox  阅读(28)  评论(0)    收藏  举报  来源