用途
求解线性方程组
{
x
≡
a
1
(
m
o
d
b
1
)
x
≡
a
2
(
m
o
d
b
2
)
…
x
≡
a
n
(
m
o
d
b
2
)
\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)
前置条件
b i b_i bi间两两互质.
做法
令
N
=
Π
b
i
N = \Pi\ b_i
N=Π bi
对于一个方程,令
t
i
t_i
ti为同余方程
N
b
i
t
i
≡
1
(
m
o
d
b
i
)
\frac{N}{b_i}t_i\equiv1(mod\ b_i)
biNti≡1(mod bi)的解.
则有一个解为
Σ
a
i
N
b
i
t
i
\Sigma\ a_i\frac{N}{b_i}t_i
Σ aibiNti
最小非负整数解:
(
x
%
N
+
N
)
%
N
(x\%N+N)\%N
(x%N+N)%N
通解:
x
+
i
∗
m
x+i*m
x+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;
}