用途
求解线性方程组
{x≡a1(mod b1)x≡a2(mod b2)…x≡an(mod b2) \left\{
\begin{aligned}
x \equiv a_1 (mod\ b_1)\\
x \equiv a_2 (mod\ b_2) \\
\ldots\\
x \equiv a_n (mod\ b_2)
\end{aligned}
\right.
⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧x≡a1(mod b1)x≡a2(mod b2)…x≡an(mod b2)
前置条件
bib_ibi间两两互质.
做法
令
N=Π biN = \Pi\ b_iN=Π bi
对于一个方程,令tit_iti为同余方程Nbiti≡1(mod bi)\frac{N}{b_i}t_i\equiv1(mod\ b_i)biNti≡1(mod bi)的解.
则有一个解为
Σ aiNbiti\Sigma\ a_i\frac{N}{b_i}t_iΣ aibiNti
最小非负整数解:(x%N+N)%N(x\%N+N)\%N(x%N+N)%N
通解:x+i∗mx+i*mx+i∗m(i为整数)
证明不会 略
模板(Luogu3868)
#include <cstdio>
#include <algorithm>
#include <cstring>
#define LL long long
using namespace std;
const int N = 15;
void exgcd(LL a,LL b,LL &gcd,LL &x,LL &y)
{
if (!b)
{
x = 1,y = 0;
gcd = a;
return;
}
exgcd(b,a % b,gcd,y,x);
y -= x * (a / b);
}
int n;
int a[N],b[N];
LL mul(LL x,LL time,LL mo)
{
LL ans = 0;
while (time)
{
if (time & 1) ans = (ans + x) % mo;
x = (x + x) % mo;
time >>= 1;
}
return ans;
}
LL CRT()
{
LL N = 1,ans = 0,gcd,x,y;
for (int i = 1 ; i <= n ; i++) N *= b[i];
for (int i = 1 ; i <= n ; i++)
{
LL k = N / b[i];
exgcd(k,b[i],gcd,x,y);
x = (x % b[i] + b[i]) % b[i];
ans = (ans + mul(mul(k,x,N),a[i],N)) % N;
}
return (ans + N) % N;
}
int main()
{
scanf("%d",&n);
for (int i = 1 ; i <= n ; i++) scanf("%d",&a[i]);
for (int i = 1 ; i <= n ; i++) scanf("%d",&b[i]);
for (int i = 1 ; i <= n ; i++) a[i] = (a[i] % b[i] + b[i]) % b[i];
printf("%lld\n",CRT());
return 0;
}