问题描述
POJ上的A+B题目虽简单,但被各种人玩出花来,链接:http://poj.org/problem?id=1000
输入a b,0≤a≤9, 0≤b≤9,输出a+b
输入样例:8 1
输出样例:9
可能长度最短代码
main(n){gets(&n);printf("%d",n%85-43);}
证明
上述代码中n
是int
类型,在get(&n)
中存储了3字节的字符数据。
令a的ascii码是ca
,b的ascii码是cb
,空格的ascii码是cs
,则
在x86平台,CPU是小端模式,所以
n
=
c
a
+
(
c
s
<
<
8
)
+
(
c
b
<
<
16
)
n = ca + (cs << 8) + (cb << 16)
n=ca+(cs<<8)+(cb<<16)
经过查表得到,
c
a
=
a
+
48
ca = a + 48
ca=a+48,
c
b
=
b
+
48
cb = b + 48
cb=b+48,
c
s
=
32
cs = 32
cs=32,
则有
n
=
a
+
48
+
(
32
<
<
8
)
+
(
(
b
+
48
)
<
<
16
)
n = a + 48 + (32 << 8) + ((b + 48) << 16)
n=a+48+(32<<8)+((b+48)<<16)
为了实现a+b,需要在保持a的因数是1的情况下,让b的因数变为1,可以使用求模的运算法则。
求模有以下两种运算法则:
a
+
b
≡
a
 
m
o
d
 
r
+
b
 
m
o
d
 
r
(
m
o
d
r
)
a
×
b
≡
a
×
(
b
 
m
o
d
 
r
)
≡
(
a
 
m
o
d
 
r
)
×
(
b
 
m
o
d
 
r
)
(
m
o
d
r
)
\begin{aligned} &a + b ≡ a\bmod r + b \bmod r&\pmod{r}\\ &a \times b ≡ a\times (b\bmod r) ≡ (a\bmod r) \times (b\bmod r) &\pmod{r} \end{aligned}
a+b≡amodr+bmodra×b≡a×(bmodr)≡(amodr)×(bmodr)(modr)(modr)
令
x
=
a
+
48
+
(
32
<
<
8
)
x = a + 48 + (32 << 8)
x=a+48+(32<<8),
y
=
(
b
+
48
)
<
<
16
y = (b + 48) << 16
y=(b+48)<<16,则
x
=
8240
+
a
≡
80
+
a
(
m
o
d
85
)
y
=
(
b
+
48
)
×
65536
≡
(
b
+
48
)
 
m
o
d
 
85
×
(
65536
 
m
o
d
 
85
)
=
b
+
48
(
m
o
d
85
)
n
=
x
+
y
≡
(
80
+
a
)
+
(
b
+
48
)
≡
a
+
b
+
43
(
m
o
d
85
)
\begin{aligned} x &= 8240 + a ≡ 80 + a &\pmod{85}\\ y &= (b+48) \times 65536 \\&≡ (b+48) \bmod 85 \times (65536 \bmod 85) \\&= b+48 &\pmod{85}\\\\ n &= x + y \\&≡ (80 + a) + (b+48) \\&≡ a + b + 43 \pmod{85} \end{aligned}
xyn=8240+a≡80+a=(b+48)×65536≡(b+48)mod85×(65536mod85)=b+48=x+y≡(80+a)+(b+48)≡a+b+43(mod85)(mod85)(mod85)
由于
0
≤
a
≤
9
,
0
≤
b
≤
9
0≤a≤9, 0≤b≤9
0≤a≤9,0≤b≤9,则
a
+
b
+
43
≤
18
+
43
=
61
<
85
⇒
(
a
+
b
+
43
)
 
m
o
d
 
85
=
a
+
b
+
43
⇒
n
 
m
o
d
 
85
=
(
a
+
b
+
43
)
 
m
o
d
 
85
=
a
+
b
+
43
\begin{aligned} &a + b + 43 ≤ 18 + 43 = 61 < 85\\ &\Rightarrow(a + b + 43) \bmod 85 = a + b + 43 \\ &\Rightarrow n \bmod 85 = (a + b + 43) \bmod 85 = a + b + 43 \end{aligned}
a+b+43≤18+43=61<85⇒(a+b+43)mod85=a+b+43⇒nmod85=(a+b+43)mod85=a+b+43
综上,
a
+
b
=
n
 
m
o
d
 
85
−
43
a + b = n \bmod 85 - 43
a+b=nmod85−43
拓展
根据这个规律,可以构造其他magic number,如 n%51-26
。
为了让b的因数变为1,找出除65536的余数是1的除数r,这样有
(
b
+
48
)
×
65536
≡
b
+
48
(
m
o
d
r
)
(b+48) \times 65536 ≡ b+48 \pmod{r}
(b+48)×65536≡b+48(modr)
所以,
n
=
a
+
48
+
(
32
×
256
)
+
(
(
b
+
48
)
×
65536
)
≡
a
+
48
+
(
32
×
256
)
+
b
+
48
≡
a
+
b
+
8288
 
m
o
d
 
r
(
m
o
d
r
)
\begin{aligned} n &= a + 48 + (32 \times 256) + ((b + 48) \times 65536) \\ &≡ a + 48 + (32 \times 256) + b+48 \\ &≡ a + b + 8288\bmod r \pmod{r} \end{aligned}
n=a+48+(32×256)+((b+48)×65536)≡a+48+(32×256)+b+48≡a+b+8288modr(modr)
为了寻找r
,对
65536
−
1
65536-1
65536−1 进行质因数分解,得到
65535
=
257
×
17
×
5
×
3
65535 = 257\times17\times5\times3
65535=257×17×5×3
容易发现,
85
=
17
×
5
85 = 17 \times 5
85=17×5 是其中 65535 的一个因数。
此外,r
还有一个条件:
a
+
b
+
8288
 
m
o
d
 
r
<
r
a + b + 8288\bmod r < r
a+b+8288modr<r
经过搜索,r = 51
也满足上述约束。