POJ 1006 – Biorhythms
试题链接:POJ 1006
一、费马小定理
若
p
p
p为素数,且
a
,
p
a, p
a,p互素,则
a
p
−
1
≡
1
(
m
o
d
p
)
a^{p-1} \equiv 1 \pmod{p}
ap−1≡1(modp)
二、欧拉定理
若
n
,
a
n, a
n,a为整数,且
n
,
a
n, a
n,a互素,则
a
ϕ
(
n
)
≡
1
(
m
o
d
n
)
a^{\phi (n)} \equiv 1 \pmod{n}
aϕ(n)≡1(modn)
其中,
ϕ
(
n
)
\phi (n)
ϕ(n)为欧拉函数,表示小于
n
n
n的正整数中与
n
n
n互质的数的数目。欧拉函数的通式为
ϕ
(
n
)
=
n
∏
i
=
1
k
(
1
−
1
p
i
)
\phi (n) = n \prod_{i=1}^{k}{\left( 1-\frac{1}{p_i} \right)}
ϕ(n)=ni=1∏k(1−pi1)
其中,
p
1
,
p
2
,
⋯
,
p
k
p_1, p_2, \cdots, p_k
p1,p2,⋯,pk为
n
n
n的所有素因数。
三、逆元
1、定义
若
a
x
≡
1
(
m
o
d
m
)
ax \equiv 1 \pmod{m}
ax≡1(modm)
则称
x
=
a
−
1
x = a^{-1}
x=a−1为
a
a
a在模
m
m
m意义下的逆元(数论倒数)。
2、求法
求解数论逆元的方法有很多,下面先介绍根据费马小定理来推出计算公式。
(1)根据费马小定理(当模为素数)
根据费马小定理
a
p
−
1
≡
1
(
m
o
d
p
)
a^{p-1} \equiv 1 \pmod{p}
ap−1≡1(modp)
则有
a
a
p
−
2
≡
1
(
m
o
d
p
)
a a^{p-2} \equiv 1 \pmod{p}
aap−2≡1(modp)
所以,
a
a
a在模
p
p
p(
p
p
p为素数)意义下的逆元
a
−
1
≡
a
p
−
2
(
m
o
d
p
)
a^{-1} \equiv a^{p-2} \pmod{p}
a−1≡ap−2(modp)
因而,我们可以使用快速幂取模来计算逆元。
(2)根据欧拉定理(对于任意模)
根据欧拉定理,不难推出
a
ϕ
(
n
)
−
1
a
≡
1
(
m
o
d
n
)
a^{\phi(n)-1} a \equiv 1 \pmod{n}
aϕ(n)−1a≡1(modn)
所以,
a
a
a在模
n
n
n意义下的逆元
a
−
1
≡
a
ϕ
(
n
)
−
1
(
m
o
d
n
)
a^{-1} \equiv a^{\phi(n)-1} \pmod{n}
a−1≡aϕ(n)−1(modn)
同样可以使用快速幂取模求得。
四、快速幂取模
1、原理
对于一个十进制正整数
n
=
b
k
−
1
b
k
−
2
⋯
b
1
b
0
‾
n = \overline{b_{k-1} b_{k-2}\cdots b_{1} b_{0}}
n=bk−1bk−2⋯b1b0可以表示为
k
k
k位二进制数,即
n
=
b
k
−
1
2
k
−
1
+
b
k
−
2
2
k
−
2
+
⋯
+
b
1
2
1
+
b
0
2
0
n = b_{k-1}2^{k-1} + b_{k-2}2^{k-2} + \cdots + b_{1}2^{1} + b_{0}2^{0}
n=bk−12k−1+bk−22k−2+⋯+b121+b020
其中,
b
i
∈
{
0
,
1
}
(
i
=
0
,
1
,
⋯
,
k
−
1
)
b_i \in \{0, 1\} (i = 0, 1, \cdots, k-1)
bi∈{0,1}(i=0,1,⋯,k−1)。
那么对于指数
x
n
=
x
b
k
−
1
2
k
−
1
+
b
k
−
2
2
k
−
2
+
⋯
+
b
1
2
1
+
b
0
2
0
=
x
b
k
−
1
2
k
−
1
⋅
x
b
k
−
2
2
k
−
2
⋯
x
b
1
2
1
⋅
x
b
0
2
0
\begin{aligned} x^{n} &= x^{b_{k-1}2^{k-1} + b_{k-2}2^{k-2} + \cdots + b_{1}2^{1} + b_{0}2^{0}} \\ &= x^{b_{k-1}2^{k-1}} \cdot x^{b_{k-2}2^{k-2}} \cdots x^{b_{1}2^{1}} \cdot x^{b_{0}2^{0}} \end{aligned}
xn=xbk−12k−1+bk−22k−2+⋯+b121+b020=xbk−12k−1⋅xbk−22k−2⋯xb121⋅xb020
其中,有一些
b
i
b_i
bi为0,即对应的指数项为1,不会影响最后的结果。如
x
11
=
x
1011
‾
2
=
x
8
⋅
x
2
⋅
x
1
x^{11} = x^{\overline{1011}_2} = x^8 \cdot x^2 \cdot x^1
x11=x10112=x8⋅x2⋅x1
x
4
x^4
x4没有出现在最后的乘积中,因为
b
2
=
0
b_2 = 0
b2=0。
而
x
2
i
=
x
2
i
−
1
⋅
2
=
x
2
i
−
1
+
2
i
−
1
=
x
2
i
−
1
⋅
x
2
i
−
1
=
(
x
2
i
−
1
)
2
x^{2^{i}} = x^{2^{i-1} \cdot 2} = x^{2^{i-1} + 2^{i-1}} = x^{2^{i-1}} \cdot x^{2^{i-1}} = \left(x^{2^{i-1}}\right)^2
x2i=x2i−1⋅2=x2i−1+2i−1=x2i−1⋅x2i−1=(x2i−1)2
所以,就可以使用迭代来计算指数,时间复杂度为 O ( n ) O(n) O(n)。
2、伪代码
// calculate (x^n) % M
int exp(int x, int n, int M)
{
int res = 1; // the answer
while (n) // for each bit of n, start from b_0
{
if (n & 1) // if b_i = 1
res = (res * x) % M; // multiply into residue
x = (x * x) % M; // x^{2^i} = (x^{2^{i-1}})^2
n >>= 1; // move to next bit b_{i+1}
}
return res;
}
五、中国剩余定理(孙子定理)
假设整数
m
1
,
m
2
,
⋯
,
m
n
m_1, m_2, \cdots, m_n
m1,m2,⋯,mn两两互素,则对于任意的整数
a
1
,
a
2
,
⋯
,
a
n
a_1, a_2, \cdots, a_n
a1,a2,⋯,an,同余方程组
{
x
≡
a
1
(
m
o
d
m
1
)
x
≡
a
2
(
m
o
d
m
2
)
⋮
x
≡
a
n
(
m
o
d
m
n
)
\left \{ \begin{aligned} x &\equiv a_1 \pmod{m_1} \\ x &\equiv a_2 \pmod{m_2} \\ &\vdots \\ x &\equiv a_n \pmod{m_n} \end{aligned} \right.
⎩⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎧xxx≡a1(modm1)≡a2(modm2)⋮≡an(modmn)
有解。
设
M
=
m
1
×
m
2
×
⋯
×
m
n
=
∏
i
=
1
n
m
i
M = m_1 \times m_2 \times \cdots \times m_n = \prod_{i=1}^{n}{m_i}
M=m1×m2×⋯×mn=i=1∏nmi
是整数
m
1
,
m
2
,
⋯
,
m
n
m_1, m_2, \cdots, m_n
m1,m2,⋯,mn的乘积,并设
M
i
=
M
m
i
M_i = \frac{M}{m_i}
Mi=miM
是除
m
i
m_i
mi以为其他
n
−
1
n-1
n−1个模的乘积,其中
i
=
1
,
2
,
⋯
,
n
i = 1, 2, \cdots, n
i=1,2,⋯,n。且记
M
i
−
1
M_{i}^{-1}
Mi−1为
M
i
M_i
Mi模
m
i
m_i
mi的逆元,即
M
i
M
i
−
1
≡
1
(
m
o
d
m
i
)
M_i M_i^{-1} \equiv 1 \pmod{m_i}
MiMi−1≡1(modmi)
则解为
x
≡
a
1
M
1
−
1
M
1
+
a
2
M
2
−
1
M
2
+
⋯
+
a
n
M
n
−
1
M
n
(
m
o
d
M
)
x \equiv a_1 M_1^{-1} M_1 + a_2 M_2^{-1} M_2 + \cdots + a_n M_n^{-1} M_n \pmod{M}
x≡a1M1−1M1+a2M2−1M2+⋯+anMn−1Mn(modM)
六、本题解答
1、推导
根据题意,设
x
x
x为从当前年第一天开始到三个高峰同时到来之间的天数,我们可以得到同余方程组
{
x
≡
p
(
m
o
d
23
)
x
≡
e
(
m
o
d
28
)
x
≡
i
(
m
o
d
33
)
\left \{ \begin{aligned} x &\equiv p \pmod{23} \\ x &\equiv e \pmod{28} \\ x &\equiv i \pmod{33} \end{aligned} \right.
⎩⎪⎨⎪⎧xxx≡p(mod23)≡e(mod28)≡i(mod33)
于是题目要求计算的从当前年给定天
d
d
d到三个高峰同时到来之间的天数
s
s
s为
s
=
(
x
−
d
)
mod
21252
s = (x - d) \text{ mod } 21252
s=(x−d) mod 21252
由于上述方程组形式已定,所以可以通过中国剩余定理人工求出解的公式,然后将特定的 p , e , i p, e, i p,e,i值代入即可。
本题中, M = 23 × 28 × 33 = 21252 M = 23 \times 28 \times 33 = 21252 M=23×28×33=21252, M 1 = 28 × 33 = 924 M_1 = 28 \times 33 = 924 M1=28×33=924, M 2 = 23 × 33 = 759 M_2 = 23 \times 33 = 759 M2=23×33=759, M 3 = 23 × 28 = 644 M_3 = 23 \times 28 = 644 M3=23×28=644。
由于
m
1
=
23
m_1 = 23
m1=23为素数,通过快速幂取模求出
M
1
M_1
M1的逆元,即
M
1
−
1
≡
M
1
m
1
−
2
(
m
o
d
m
1
)
M_1^{-1} \equiv M_1^{m_1-2} \pmod{m_1}
M1−1≡M1m1−2(modm1)
得到
M
1
−
1
≡
6
(
m
o
d
23
)
M_1^{-1} \equiv 6 \pmod{23}
M1−1≡6(mod23)。
又 m 2 = 28 = 2 2 × 7 m_2 = 28 = 2^2 \times 7 m2=28=22×7,其素因数为2和7,则 ϕ ( m 2 ) = 28 × ( 1 − 1 2 ) × ( 1 − 1 7 ) = 12 \phi(m_2) = 28 \times \left( 1 - \frac{1}{2} \right) \times \left( 1 - \frac{1}{7} \right) = 12 ϕ(m2)=28×(1−21)×(1−71)=12,于是 M 2 − 1 ≡ 19 ( m o d 28 ) M_2^{-1} \equiv 19 \pmod{28} M2−1≡19(mod28)。
同理 m 3 = 33 = 3 × 11 m_3 = 33 = 3 \times 11 m3=33=3×11,其素因数为3和11,则 ϕ ( m 3 ) = 33 × ( 1 − 1 3 ) × ( 1 − 1 11 ) = 20 \phi(m_3) = 33 \times \left( 1 - \frac{1}{3} \right) \times \left( 1 - \frac{1}{11} \right) = 20 ϕ(m3)=33×(1−31)×(1−111)=20,于是 M 3 − 1 ≡ 2 ( m o d 33 ) M_3^{-1} \equiv 2 \pmod{33} M3−1≡2(mod33)。
所以,方程组的解为
x
≡
p
×
M
1
×
M
1
−
1
+
e
×
M
2
×
M
2
−
1
+
m
×
M
3
×
M
3
−
1
(
m
o
d
M
)
≡
5544
p
+
14421
e
+
1288
i
(
m
o
d
21252
)
\begin{aligned} x &\equiv p \times M_1 \times M_1^{-1} + e \times M_2 \times M_2^{-1} + m \times M_3 \times M_3^{-1} \pmod{M} \\ &\equiv 5544p + 14421e + 1288i \pmod{21252} \end{aligned}
x≡p×M1×M1−1+e×M2×M2−1+m×M3×M3−1(modM)≡5544p+14421e+1288i(mod21252)
2、代码
#include <stdio.h>
int main()
{
int p, e, i, d, x, s;
int cnt = 0;
while (scanf("%d %d %d %d", &p, &e, &i, &d) && p >= 0)
{
++cnt;
x = (5544 * p + 14421 * e + 1288 * i) % 21252;
s = (21252 + x - d) % 21252;
if (s == 0)
s = 21252;
printf("Case %d: the next triple peak occurs in %d days.\n", cnt, s);
}
return 0;
}