• 拓展中国剩余定理(excrt)


    问题

    求解同余方程组

    其中各个方程的模数为不一定两两互质的整数, 求x的最小非负整数解

    求解

    假设已经求出前k-1个方程组成的同余方程组的一个解为x

    且有M=lcm(mo[1],mo[2],mo[3],...,mo[k-1])

    则前k-1个方程的方程组通解为x+i*M 

    因为M为前面方程模数的最小公倍数,所以M可以整除任意一个模数,所以方程组加上或减去M对于方程的同余性没有影响。

    那么对于加入第k个方程后的方程组

    我们就是要求一个正整数t,使得 x+tM≡yu[k](mod mo[k])

    转化一下上述式子得 tM≡yu[k]x(mod mo[k])

    对于这个式子我们已经可以通过扩展欧几里得求解t

    若该同余式无解,则整个方程组无解, 若有,则前k个同余式组成的方程组的一个解解为xk=x+t*M

    所以整个算法的思路就是求解k次扩展欧几里得

    洛谷 P4777

    #include<bits/stdc++.h>
    using namespace std;
    #define ll __int128
    ll ans,x,y,a,b,c,yu[100005],mo[100005],M,n;
    long long read()//int 128好像只能用快读
    {
        ll f=1,x=0;
        char ss=getchar();
        while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
        while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
        return f*x;
    }
    long long gcd(ll a,ll b)
    {
    	ll c;
    	while(a%b)
    	{
    		c=a%b;
    		a=b;
    		b=c;
    	}
    	return b;
    }
    long long lcm(ll a,ll b)
    {
    	return a/gcd(a,b)*b;
    }
    void exgcd(ll a,ll b)
    {
    	if(b==0)
    	{
    		x=1;y=0;
    		return;
    	}
    	exgcd(b,a%b);
    	ll tem=x;
    	x=y;
    	y=tem-a/b*y;
    }
    long long excrt()
    {
    	M=mo[1];ans=yu[1];//特判第一个方程
    	for(int i=2;i<=n;i++)
    	{
    		exgcd(M,mo[i]);//求解方程 t*M+y*mo[i]=yu[i]-ans;
    		ll gcdd=gcd(M,mo[i]);
    		if((yu[i]-ans)%gcdd!=0)return -1;//如果(yu[i]-ans)不是gcd(M,mo[i])的倍数,则根据裴蜀定理,方程无解
    		x*=(yu[i]-ans)/gcdd;//刚才求出的是方程 t*M+y*mo[i]==gcd(M,mo[i])的解,现在将方程解出的x,y同时扩大倍数,就成了方程真正的解。但y没有用,只是个比例系数,就不管了。
    		ans=ans+x*M;//上面的解析有说,更新答案
    		M=M/gcd(M,mo[i])*mo[i];//更新M的值
    		ans=(ans%M+M)%M;//之前的答案只是一个肯定成立的解,现在把ans改成在当前余数系下的最小非负整数答案
    	}
    	return ans;
    }
    int main()
    {
        n=read();
        for(ll i=1;i<=n;i++)
            mo[i]=read(),yu[i]=read();
        cout<<excrt();
        return 0;
    }
    

      

  • 相关阅读:
    JSP页面
    JSP简介
    常量与变量的声明与使用
    AJAX无刷新上传图片
    JSP连接MySql数据库
    运算符与表达式
    世界级的javascript ajax client端UI库 Ext学习笔记 menu组件 和 toolbar组件
    OOD/OOA基本原则
    Java字符编码转换过程说明
    正则表达式系统教程
  • 原文地址:https://www.cnblogs.com/oierjzy/p/11232187.html
Copyright © 2020-2023  润新知