• 中国剩余定理


    中国剩余定理

    讲解

    对于这种类型的方程组,求一个合法的(x)

    [egin{cases} x≡a_1 pmod {r_1}\ x≡a_2 pmod {r_2}\ x≡a_3 pmod {r_3}\ ...\ x≡a_n pmod {r_n} end{cases}]

    其中(r_1,r_2,r_3,...,r_n)互质,这就是中国剩余定理解决的问题

    其实我们可以直接构造出一个特殊解

    (A_i=prod_{j e i}r_j),因为各个(r_i)互质,所以(A_i)(r_i)也是互质的,所以一定存在一个(c_i),使得(c_i*A_i\% r_i=1)

    (x_i=c_i*A_i*a_i),则(x_i\% r_i=a_i,x_i\% r_j=0|j e i)

    这意味着什么?把所有的(x_i)加起来就是我们要求的解(x)了!

    (R=prod_{i=1}^{n}r_i),对于任意一个解(x),我们将其加上(R)的任意倍数也同样成立

    通解为:

    (x=sum_{i=1}^{n}c_i*A_i*a_i+p*R)

    其中(p)为任意整数

    代码

    (c_i)相当于求(A_i)的逆元,但是由于(r_i)不一定是质数,只是和(A_i)互质而已,所以不能用快速幂求,要用扩欧

    void exgcd(LL a,LL b,LL &x,LL &y)
    {
    	if(!b) x = 1,y = 0;
    	else
    	{
    		exgcd(b,a%b,y,x);
    		y -= a/b*x;
    	}
    }
    LL CRT()
    {
    	LL s = 1,ret = 0;
    	for(int i = 1;i <= n;++ i) s *= r[i];
    	for(int i = 1;i <= n;++ i)
    	{
    		LL x,y;
    		exgcd(s/r[i],r[i],x,y);
    		x = (x + r[i]) % r[i];
    		ret = (ret + a[i] * (s / r[i]) % s * x % s) % s;
    	}
    	return ret;
    }
    

    扩展中国剩余定理

    讲解

    扩展中国剩余定理是用来解决(r_i)各自不互质的情况的问题

    对于扩展中国剩余定理,它所做的事情其实是将两个方程不断合并,最后剩下一个方程即可得出最终解

    假设我们要合并的两个方程为:

    [egin{cases} x≡a_1 pmod {r_1}\ x≡a_2 pmod {r_2} end{cases}]

    我们的目标是将其合并成(x≡? pmod {lcm(r_1,r_2)})的形式

    我们可将两个方程化为:(x=a_1+s_1*r_1=a_2+s_2*r_2),其中(s_1,s_2)为整数

    将其移项可得(s_1*r_1-s_2*r_2=a_2-a_1)

    我们可以通过扩欧求得一组特解((s_1',s_2')),当然如果无解就可以直接在这里判断了

    然后我们就可以得到(s_1)的通解(s_1=s_1'+k*(r_2/gcd(r_1,r_2))),所以为了防爆,我们在求出(s_1')之后也可以对其取模(r_2/gcd(r_1,r_2))

    然后我们将(s_1)代回原方程,可得(x=a_1+(s_1'+k*(r_2/gcd(r_1,r_2)))*r_1=a_1+s_1'*r_1+k*lcm(r_1,r_2))

    我们即可得到方程(x≡a_1+s_1'*r_1 pmod{lcm(r_1,r_2)})

    代码

    void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
    {
    	if(!b) d = a,x = 1,y = 0;
    	else
    	{
    		exgcd(b,a%b,d,y,x);
    		y -= a/b*x;
    	}
    }
    LL exCRT()
    {
    	for(int i = 1;i < n;++ i)
    	{
    		LL x,y,d;
    		exgcd(r[i],r[i+1],d,x,y);
    		if((a[i+1] - a[i]) % d) return -1;
    		x = ((a[i+1] - a[i]) / d * x % (r[i+1] / d) + r[i+1] / d) % (r[i+1] / d);
    		LL lcm = r[i] * r[i+1] / d;
    		a[i+1] = (x * r[i] % lcm + a[i]) % lcm;
    		r[i+1] = lcm;
    	}
    	return a[n];
    }
    
  • 相关阅读:
    JS === 飞机吐子弹
    React === 几个小问题
    CSS === P标签加了定位,里面文字的问题
    css边框的一些属性
    Spring整合quart初识
    Jenkins部署报weblogic.deploy.api.tools.deployer.DeployerException: Java heap space
    js跳转新窗口
    Idea中运行项目时出现:未结束的字符串解决方案
    Idea中类上有叉的解决方法
    清除eclipse,STS workspace历史记录
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/13610292.html
Copyright © 2020-2023  润新知