中国剩余定理(CRT)
我好蔡啊
不学这个东东我连任意模数(NTT)都学不了
问题
中国剩余定理用于求解同余方程组
其中(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)
问题
扩展中国剩余定理用于求解同余方程组
其中(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;
}
后记
感觉这种数学的东西还得多学多记多背……
本人版权意识薄弱……