拓展欧几里得模板
求解
g
c
d
(
a
,
b
)
=
a
x
+
b
y
,
x
gcd(a,b)=ax+by,x
gcd(a,b)=ax+by,x 与
y
y
y 的值
由
g
c
d
(
a
,
b
)
=
gcd(a,b)=
gcd(a,b)=
g
c
d
(
b
,
a
%
b
)
gcd(b,a\%b)
gcd(b,a%b)
a
x
+
b
y
=
b
x
+
(
a
−
⌊
a
b
⌋
∗
b
)
y
ax+by=bx+(a-\lfloor\frac{a}{b}\rfloor*b)y
ax+by=bx+(a−⌊ba⌋∗b)y
a
x
+
b
y
=
a
y
+
b
(
x
−
a
/
b
∗
y
)
ax+by=ay+b(x-a/b*y)
ax+by=ay+b(x−a/b∗y)
发现
a
x
ax
ax 对应
a
y
ay
ay 只有一项不相等,直接交换即可
a
x
+
b
y
=
a
x
+
b
(
y
−
⌊
a
b
⌋
x
)
ax+by=ax+b(y-\lfloor\frac{a}{b}\rfloor x)
ax+by=ax+b(y−⌊ba⌋x)
a*x+b*y=c存在解的充分必要条件c%__gcd(a,b)==0
a
x
+
b
y
=
c
ax+by=c
ax+by=c等价于
a
x
≡
c
(
m
o
d
b
)
ax\equiv c\pmod b
ax≡c(modb)有解的充分必要条件c%gcd(a,b)=0
例:求解
a
x
≡
1
(
m
o
d
b
)
ax\equiv1\pmod b
ax≡1(modb)即为:
a
x
+
b
y
≡
1
(
m
o
d
b
)
ax+by\equiv1 \pmod {b}
ax+by≡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.
⎩
⎨
⎧akmkMti≡ak(modmk)∀i!=kaimkMti≡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=1naimiMti
通解为
x
+
k
M
(
k
∈
Z
)
x+kM(k\in Z)
x+kM(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;
}