拓展欧几里得模板
求
解
g
c
d
(
a
,
b
)
=
a
∗
x
+
b
∗
y
,
x
与
y
的
值
求解gcd(a,b)=a*x+b*y,x与y的值
求解gcd(a,b)=a∗x+b∗y,x与y的值
由
g
c
d
(
a
,
b
)
=
由gcd(a,b)=
由gcd(a,b)=
g
c
d
(
b
,
a
gcd(b,a
gcd(b,a%
b
b
b
)
)
)
a
∗
x
+
b
∗
y
=
b
∗
x
+
(
a
−
⌊
a
b
⌋
∗
b
)
∗
y
a*x+b*y=b*x+(a-\lfloor\frac{a}{b}\rfloor*b)*y
a∗x+b∗y=b∗x+(a−⌊ba⌋∗b)∗y
a
∗
x
+
b
∗
y
=
a
∗
y
+
b
∗
(
x
−
a
/
b
∗
y
)
a*x+b*y=a*y+b*(x-a/b*y)
a∗x+b∗y=a∗y+b∗(x−a/b∗y)
发
现
a
∗
x
对
应
a
∗
y
只
有
一
项
不
相
等
,
直
接
交
换
即
可
发现a*x对应a*y只有一项不相等,直接交换即可
发现a∗x对应a∗y只有一项不相等,直接交换即可
a
∗
x
+
b
∗
y
=
a
∗
x
+
b
∗
(
y
−
⌊
a
b
⌋
∗
x
)
a*x+b*y=a*x+b*(y-\lfloor\frac{a}{b}\rfloor*x)
a∗x+b∗y=a∗x+b∗(y−⌊ba⌋∗x)
a*x+b*y=c存在解的充分必要条件c%__gcd(a,b)==0
a
∗
x
+
b
∗
y
=
c
a*x+b*y=c
a∗x+b∗y=c等价于
a
∗
x
≡
c
(
m
o
d
b
)
a*x\equiv c\pmod b
a∗x≡c(modb)有解的充分必要条件c%gcd(a,b)=0
例:求解
a
∗
x
≡
1
(
m
o
d
b
)
a*x\equiv1\pmod b
a∗x≡1(modb)即为:
a
∗
x
+
b
∗
y
≡
1
(
m
o
d
b
)
a*x+b*y\equiv1 \pmod {b}
a∗x+b∗y≡1(modb)的解
当1%__gcd(a,b)==0时可直接用模板解。
int exgcd(int a,int b,int &x,int &y){
if(b==0){
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
中国剩余定理
{
x
≡
a
1
(
m
o
d
m
1
)
x
≡
a
2
(
m
o
d
m
2
)
.
.
.
x
≡
a
n
(
m
o
d
m
n
)
(
m
1
.
.
.
m
n
两
两
互
质
)
\left\{ \begin{aligned} x\equiv a_1 \pmod {m_1}\\ x\equiv a_2 \pmod {m_2}\\ ...\\ x\equiv a_n \pmod {m_n} \end{aligned} \right.(m_1...m_n两两互质)
⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧x≡a1(modm1)x≡a2(modm2)...x≡an(modmn)(m1...mn两两互质)
设
M
=
∏
i
=
1
n
m
i
,
t
k
M=\prod_{i=1}^{n}m_i,t_k
M=∏i=1nmi,tk为
M
m
k
∗
t
k
≡
1
(
m
o
d
m
k
)
\frac{M}{m_k}*t_k\equiv1\pmod {m_k}
mkM∗tk≡1(modmk)的最小非负整数解
其中
∀
i
!
=
k
M
m
i
∗
t
i
≡
0
(
m
o
d
m
i
)
\forall {_{i!=k}}\frac{M}{m_i}*t_i\equiv0 \pmod {m_i}
∀i!=kmiM∗ti≡0(modmi)
两边
∗
a
[
i
]
*a[i]
∗a[i]有
{
a
k
∗
M
m
k
∗
t
i
≡
a
k
(
m
o
d
m
k
)
∀
i
!
=
k
a
i
∗
M
m
k
∗
t
i
≡
0
(
m
o
d
m
i
)
\left\{ \begin{aligned} a_k*\frac{M}{m_k}*t_i\equiv a_k\pmod {m_k}\\ \forall{_{i!=k}}a_i*\frac{M}{m_k}*t_i\equiv 0 \pmod {m_i} \end{aligned} \right.
⎩⎪⎪⎨⎪⎪⎧ak∗mkM∗ti≡ak(modmk)∀i!=kai∗mkM∗ti≡0(modmi)
则有一个解为
x
=
∑
i
=
1
n
a
i
∗
M
m
i
∗
t
i
x=\sum_{i=1}^{n}a_i*\frac{M}{m_i}*t_i
x=∑i=1nai∗miM∗ti
通解为
x
+
k
∗
M
(
k
∈
Z
)
x+k*M(k\in Z)
x+k∗M(k∈Z)
P3868 [TJOI2009] 猜数字
#include <iostream>
using namespace std;
using ll = long long ;
int n;
ll read(){
char ch=getchar();
int f=1;
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
ll x=0;
while(isdigit(ch)){
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return f*x;
}
ll a[20],b[20];
ll mul(ll a,ll b,ll p){///龟速乘
ll r=0;
while(b){
if(1&b)r=(r+a)%p;
a=(a+a)%p;
b>>=1;
}
return r;
}
/**
gcd(a,b)=gcd(b,a%b)
a*x+b*y=b*x+(a-a/b*b)*y
a*x+b*y=a*y+b*(x-a/b*y)
*/
void exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1,y=0;
return ;
}
exgcd(b,a%b,y,x);
y-=a/b*x;
}
ll china(){
ll M=1;
for(int i=1;i<=n;i++) M*=b[i];
ll ans=0;
ll x,y;
for(int i=1;i<=n;i++)
{
ll tp=M/b[i];
exgcd(tp,b[i],x,y);
x=(x%b[i]+b[i])%b[i];
ans=(ans+mul(mul(tp,x,M),a[i],M))%M;
}
return (ans+M)%M;
}
int main()
{
n=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) b[i]=read(),a[i]=(a[i]%b[i]+b[i])%b[i];
printf("%lld",china());
return 0;
}