zoukankan      html  css  js  c++  java
  • 中国剩余定理与扩展中国剩余定理

    中国剩余定理(CRT)

    我好蔡啊
    不学这个东东我连任意模数(NTT)都学不了

    问题

    中国剩余定理用于求解同余方程组

    [ left{ egin{aligned} x≡a_1(mod m_1)\ x≡a_2(mod m_2)\ ......\ x≡a_k(mod m_k) end{aligned} ight. ]

    其中(m_1,m_2,...,m_k)两两互质
    (x)的最小非负整数解

    定理

    (M=prod_{i=1}^km_i),也就是它们的最小公倍数
    (t_i)({Mover m_i}t_i≡1(mod m_i))的最小非负整数解
    那么有一个(x)解为(sum_{i=1}^ka_i{Mover m_i}t_i)
    通解为(x+kM(kin )),最小非负整数解为((x\% M+M)\%M)

    证明

    对于(Mover m_i),它一定是其他(m)的倍数且不整除(m_i)(注意限制)
    那么(∀k≠i,a_i{Mover m_i}t_i≡0(mod m_k)),这个是因为({Mover m_i}mod m_k=0)
    由于({Mover m_i}t_i≡1(mod m_i)),所以(a_i{Mover m_i}t_i≡a_i(mod m_i))
    又因为(x=sum_{i=1}^ka_i{Mover m_i}t_i),代入方程组,方程组成立

    code

    容易发现因为({Mover m_i}t_i≡1(mod m_i))
    其实就是求({Mover m_i})关于(m_i)逆元
    扩欧实现好了

    inline ll exgcd(ll a,ll b,ll &x,ll &y)
    {
    	if (b==0){x=1,y=0;return a;}
    	ll ans=exgcd(b,a%b,y,x);
    	y-=x*(a/b);return ans;
    }
    inline ll CRT(ll a[],ll m[],ll n)
    {
    	ll M=1ll,x,y,ans=0ll;
    	fo(i,1,n)M*=m[i];
    	fo(i,1,n)
    	{
    		ll tmp=M/m[i];exgcd(tmp,m[i],x,y);
    		ans=(ans+a[i]*x*tmp)%M;
    	}
    	return (ans+M)%M;
    }
    

    扩展中国剩余定理(EXCRT)

    问题

    扩展中国剩余定理用于求解同余方程组

    [ left{ egin{aligned} x≡a_1(mod m_1)\ x≡a_2(mod m_2)\ ......\ x≡a_k(mod m_k) end{aligned} ight. ]

    其中(m_1,m_2,...,m_k)不保证两两互质
    (x)的最小非负整数解

    求解

    设前(k-1)条方程组成的方程组的一个解为(x)
    (M=prod_{i=1}^{k-1}m_i),那么通解就为(x+kM(kin))

    那么考虑加入第(k)条方程,即求一个(tinN^+),使
    (x+tM≡a_k(mod m_k)),也就是(tM≡a_k-x(mod m_k))
    由于(M,a_k,x,m_k)都已知,可以看作(ax≡c(mod b))
    这个也可以用扩欧解

    扩欧可以直接解出(ax+by=gcd(a,b))的解(x_0,y_0)
    于是如果直接解(ax+by=c)(x_0)还要除掉({gcd(a,b)over c})就是(x_0cover gcd(a,b))
    原方程相当于(axmod b=c),转化为(ax+by=c),用上面的方法解就好了
    注意如果不满足(gcd(a,b)|c),这条方程无解,整个方程组也无解
    好像就是这样了,一共要做(n-1)次扩欧,注意各种取模细节

    code

    inline ll mul(ll x,ll y,ll mod)
    {
    	return (x*y-(ll)((long double)x/mod*y)*mod+mod)%mod;     
    }
    inline ll EXCRT(ll a[],ll m[],ll n)
    {
    	ll M=m[1],x,y,ans=a[1];
    	fo(i,2,n)
    	{
    		ll gcd=exgcd(M,m[i],x,y),tmp=(a[i]-ans%m[i]+m[i])%m[i];
    		if (tmp%gcd!=0)return -1;
    		x=mul(x,tmp/gcd,m[i]/gcd);
    		ans+=x*M,M*=m[i]/gcd,ans=(ans%M+M)%M;
    	}
    	return (ans%M+M)%M;
    }
    

    后记

    感觉这种数学的东西还得多学多记多背……
    本人版权意识薄弱……

  • 相关阅读:
    【Flask项目】 python学习第一章
    【Oracle】整理oracle命令 转载
    C# 利用SQLite对.DB和.logdb加密和解密和SQLite创建数据库
    C# 利用ICSharpCode.SharpZipLib实现在线加密压缩和解密解压缩
    Django Cookie 和 Sessions 应用
    Django中添加富文本编辑器
    Django实现简单分页功能
    Xadmin集成富文本编辑器ueditor
    Django安装Xadmin步骤
    Pycharm小技巧--使用正则进行查找和批量替换
  • 原文地址:https://www.cnblogs.com/horizonwd/p/11307384.html
Copyright © 2011-2022 走看看