我好蔡啊
不学这个东东我连任意模数 N T T NTT NTT都学不了
中国剩余定理用于求解同余方程组
{ x ≡ a 1 ( m o d    m 1 ) x ≡ a 2 ( m o d    m 2 ) . . . . . . x ≡ a k ( m o d    m k ) \left\{ \begin{aligned} x≡a_1(\mod m_1)\\ x≡a_2(\mod m_2)\\ ......\\ x≡a_k(\mod m_k) \end{aligned} \right. ⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧x≡a1(modm1)x≡a2(modm2)......x≡ak(modmk)
其中 m 1 , m 2 , . . . , m k m_1,m_2,...,m_k m1,m2,...,mk两两互质
求 x x x的最小非负整数解
令 M = ∏ i = 1 k m i M=\prod_{i=1}^km_i M=∏i=1kmi,也就是它们的最小公倍数
设 t i t_i ti为 M m i t i ≡ 1 ( m o d    m i ) {M\over m_i}t_i≡1(\mod m_i) miMti≡1(modmi)的最小非负整数解
那么有一个 x x x解为 ∑ i = 1 k a i M m i t i \sum_{i=1}^ka_i{M\over m_i}t_i ∑i=1kaimiMti
通解为 x + k M ( k ∈ Z ) x+kM(k\in \Z) x+kM(k∈Z),最小非负整数解为 ( x % M + M ) % M (x\% M+M)\%M (x%M+M)%M
对于 M m i M\over m_i miM,它一定是其他 m m m的倍数且不整除 m i m_i mi(注意限制)
那么 ∀ k ≠ i , a i M m i t i ≡ 0 ( m o d    m k ) ∀k≠i,a_i{M\over m_i}t_i≡0(\mod m_k) ∀k̸=i,aimiMti≡0(modmk),这个是因为 M m i m o d    m k = 0 {M\over m_i}\mod m_k=0 miMmodmk=0
由于 M m i t i ≡ 1 ( m o d    m i ) {M\over m_i}t_i≡1(\mod m_i) miMti≡1(modmi),所以 a i M m i t i ≡ a i ( m o d    m i ) a_i{M\over m_i}t_i≡a_i(\mod m_i) aimiMti≡ai(modmi)
又因为 x = ∑ i = 1 k a i M m i t i x=\sum_{i=1}^ka_i{M\over m_i}t_i x=∑i=1kaimiMti,代入方程组,方程组成立
容易发现因为 M m i t i ≡ 1 ( m o d    m i ) {M\over m_i}t_i≡1(\mod m_i) miMti≡1(modmi)
其实就是求 M m i {M\over m_i} miM关于 m i m_i mi的逆元
扩欧实现好了
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;
}
扩展中国剩余定理用于求解同余方程组
{ x ≡ a 1 ( m o d    m 1 ) x ≡ a 2 ( m o d    m 2 ) . . . . . . x ≡ a k ( m o d    m k ) \left\{ \begin{aligned} x≡a_1(\mod m_1)\\ x≡a_2(\mod m_2)\\ ......\\ x≡a_k(\mod m_k) \end{aligned} \right. ⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧x≡a1(modm1)x≡a2(modm2)......x≡ak(modmk)
其中 m 1 , m 2 , . . . , m k m_1,m_2,...,m_k m1,m2,...,mk不保证两两互质
求 x x x的最小非负整数解
设前 k − 1 k-1 k−1条方程组成的方程组的一个解为 x x x
令 M = ∏ i = 1 k − 1 m i M=\prod_{i=1}^{k-1}m_i M=∏i=1k−1mi,那么通解就为 x + k M ( k ∈ Z ) x+kM(k\in\Z) x+kM(k∈Z)
那么考虑加入第 k k k条方程,即求一个 t ∈ N + t\in\N^+ t∈N+,使
x + t M ≡ a k ( m o d    m k ) x+tM≡a_k(\mod m_k) x+tM≡ak(modmk),也就是 t M ≡ a k − x ( m o d    m k ) tM≡a_k-x(\mod m_k) tM≡ak−x(modmk)
由于 M , a k , x , m k M,a_k,x,m_k M,ak,x,mk都已知,可以看作 a x ≡ c ( m o d    b ) ax≡c(\mod b) ax≡c(modb)
这个也可以用扩欧解
扩欧可以直接解出 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的解 x 0 , y 0 x_0,y_0 x0,y0
于是如果直接解 a x + b y = c ax+by=c ax+by=c, x 0 x_0 x0还要除掉 gcd ( a , b ) c {\gcd(a,b)\over c} cgcd(a,b)就是 x 0 c gcd ( a , b ) x_0c\over \gcd(a,b) gcd(a,b)x0c
原方程相当于 a x m o d    b = c ax\mod b=c axmodb=c,转化为 a x + b y = c ax+by=c ax+by=c,用上面的方法解就好了
注意如果不满足 g c d ( a , b ) ∣ c gcd(a,b)|c gcd(a,b)∣c,这条方程无解,整个方程组也无解
好像就是这样了,一共要做 n − 1 n-1 n−1次扩欧,注意各种取模细节
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;
}
感觉这种数学的东西还得多学多记多背……
本人版权意识薄弱……
本博客部分知识学习于
https://blog.csdn.net/niiick/article/details/80229217