数学游戏
洗牌
洗牌是这样一个过程: 先把一堆牌从正中间分成两堆,前一半是第一堆,后一半是第二堆。然后以第二堆的第一张,第一堆的第一张,第二堆的第二张,第一堆的第二张… …这样的顺序重排。52张牌洗牌几次可以回到最初的顺序?
1
2
3
4
5
6
7
8
9
10a="abcdefghijklmnopqrstuvwxyz"
b=a+a.upper()
c=b
cnt=0
while(True):
c="".join([i+j for i,j in zip(C[:26],c[26:])])
cnt+=1
if(c==b):
break
print(cnt)
异或的期望
题目
从1,2,3,……98,99,2015这100个数中任意选择若干个数(可能为0)求异或,试求异或的期望值
根据期望的性质, \(E(X+Y)=E(X)+E(Y)\)
可以把这些数按位拆分, 逐位来处理期望值
1 | 2015) bin( |
注意到除了2015外, 每个数都小于128, 故可以单独处理高四位和低七位
1 | for i in range(1,100)] A=[i |
我们已经得到了这十一个二进制位上1的个数分别是
[1, 1, 1, 1, 37, 36, 49, 49, 49, 51, 51]
所以问题转化为100个元素里有k个元素a, 任取若干(可为0)元素其中元素a的个数为奇数的概率
\[\begin{align}P(不知道写啥) & = \cfrac{(C_{k}^{1}+C_{k}^{3}+C_{k}^{5}+C_{k}^{7}+...)2^{100-k}}{2^{100}}\\ &= \cfrac{(C_{k}^{1}+C_{k}^{3}+C_{k}^{5}+C_{k}^{7}+...)}{2^{k}}\\ &= \cfrac{2^{k}/2}{2^{k}}\\ &= \cfrac{1}{2}\end{align}\]
首先解释一下这个算式的意义, 分母为100个元素的全部子集的个数, 分子则是K个元素取到奇数的情况个数与其余100-k个元素的全部子集数的乘积, 这个弹夹和背包连在一起, 它就是一个平底锅, 我想大家是没有异议的
而后嘛, 带大家复习一下高中的知识了
\((C_{k}^{1}+C_{k}^{3}+C_{k}^{5}+C_{k}^{7}+...)=2^k/2\)
天理何在?
虽然我并不是很喜欢二项式定理来证明这个, 但无疑它是打出来说清楚比较方便的
\((a+b)^n=C_{n}^{0}a^{n}+C_{n}^{1}a^{n-1}b^{1}+C_{n}^{2}a^{n-2}b^{2}+C_{n}^{3}a^{n-3}b^{3}+...\)
令a=1可以得到
\((1+x)^n=C_{n}^{0}+C_{n}^{1}x^{1}+C_{n}^{2}x^{2}+C_{n}^{3}x^{3}+...\)
再分别令x=1, x=-1得
\((1+1)^n=C_{n}^{0}+C_{n}^{1}+C_{n}^{2}+C_{n}^{3}+C_{n}^{4}+C_{n}^{5}+C_{n}^{6}+C_{n}^{7}+...\)
\((1-1)^n=C_{n}^{0}-C_{n}^{1}+C_{n}^{2}-C_{n}^{3}+C_{n}^{4}-C_{n}^{5}+C_{n}^{6}-C_{n}^{7}+...\)
\((1+1)^n-(1-1)^n=2(C_{n}^{1}+C_{n}^{3}+C_{n}^{5}+C_{n}^{7}+...)\)
\(C_{n}^{1}+C_{n}^{3}+C_{n}^{5}+C_{n}^{7}+...=\cfrac{(1+1)^n-(1-1)^n}{2}=\cfrac{2^n}{2}\)
其实观察杨辉三角可以立得奇偶次项系数和一样多(都等于上一行系数和)
尝试了一下, 无论是画图还是用组合数恒等式, 都说不清, 果断弃疗
既然每一位上的异或结果为1的概率都是1/2
那么答案就理所当然的是(11111111111)2/2 = 2047/2 = 1023.5
……吗?
\(C_{n}^{1}+C_{n}^{3}+C_{n}^{5}+C_{n}^{7}+...=\cfrac{(1+1)^n-(1-1)^n}{2}=\cfrac{2^n}{2}\)
第一个等号没问题
第二个等号问题很大
\(\cfrac{(1+1)^n-(1-1)^n}{2}=\cfrac{2^n}{2}\)
这一步其实默认了\((1-1)^{n}=0\)
\(0^{n}=0\)成立应当在n≥1时
当n0=时,\(0^{0}\)不存在
此时不能断定\(\cfrac{(1+1)^0-(1-1)^0}{2}=\cfrac{1}{2}\)此时不妨换一个角度想, 0个元素中取到奇数个元素的情况裆燃是有0种可能
所以当k=0时取到奇数个a的概率为0, 否则概率为1/2
像之前那样求出来每一位上1的个数并非必要
such as [1, 1, 1, 1, 51, 51, 49, 49, 49, 36, 37]
只需要判断每一位上是否有1即可
譬如在此题目中把2015(11111011111)换成1887(11101011111)
最终答案就变成了1919/2=959.5 (快拿去坑害他人吧233333)
猜硬币
孙膑庞涓张仪都是鬼谷子的徒弟.一天鬼谷子出了这道题目: 鬼谷子抛一枚均匀的硬币三次,分别把三次的结果写在三个人额头上.每个人都可以看到别人头上的字但看不到自己头上的字.现在三个人同时猜自己头上的字.可以猜正,反,或者跳过.如果至少有一人猜对自己的字且无人猜错(猜跳过既不算对也不算错),则集体获胜.如果三人都会采取最佳策略,且这一点本身也成为共识,那么获胜的概率是多少?
策略: 仅在看到另两人额头上字相同时, 猜与其相反的结果, 否则跳过.
这种策略获胜的概率是75%
真实情况 | 孙膑 | 庞涓 | 张仪 | 结果 |
---|---|---|---|---|
000 | 猜错 | 猜错 | 猜错 | 失败 |
001 | 猜对 | 获胜 | ||
010 | 猜对 | 获胜 | ||
011 | 猜对 | 获胜 | ||
100 | 猜对 | 获胜 | ||
101 | 猜对 | 获胜 | ||
110 | 猜对 | 获胜 | ||
111 | 猜错 | 猜错 | 猜错 | 失败 |
可以看到每个人都有两次猜对两次猜错, 猜对猜错的总数都是6次
此种策略把猜错的可能性尽可能的集中到了两种具体的情况中去, 岂不美哉
但其实这个答案不是我想出来的, 而是写了个程序试出来了,恰好想到的第二个策略就碰上了.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29def method(B,C):
if (B!=C):
return 0
if (B==C):
return -B
def subJudge(x,y):
if x==0:
return None
return x==y
def judge(A,B,C):
if (A,B,C).count(False)>0:
return False
if (A,B,C).count(True)>0:
return True
return False
cnt=0
for A in (-1,1):
for B in (-1,1):
for C in (-1,1):
a=subJudge(method(B,C),A)
b=subJudge(method(A,C),B)
c=subJudge(method(B,A),C)
#print(a,b,c)
if judge(a,b,c):
cnt+=1
print(cnt)
构造递推
一个数只用 1,2,3,4这四种数字组成,而且相近的两位数永远相差1,比如1234321, 1212121等。 这样的n位数有多少个?
不妨把每一位上的数字分成两组, {1,4}和{2,3}
前一位是 {1,4}的情况下, 当前位可以是 {2,3}
前一位是 {2,3}的情况下, 当前位可以是 {1,2,3,4} = {1,4} + {2,3}
自左向右数第n位为{2,3}的数字的个数计为\(A_{n}\), 为{1,4}的个数计为\(B_{n}\)
易知\(A_{1}=B_{1}=2\)
我们所求的个数记作\(C_{n}=A_{n}+B_{n}\)
由之前的叙述可得递推关系:
\(A_{n+1}=A_{n}+B_{n}\)
\(B_{n+1}=A_{n}\)
故可以消去数列\(B_{n}\)有:
\(A_{0}=B_{1}=2\)
\(C_{n}=A_{n+1}=A_{n}+A_{n-1}\)
而后即是求解斐波那契数列了, 方法很多, 就不写了, 我比较喜欢矩阵快速幂的方法, 不涉及浮点数运算, 实优雅也
鸽巢原理
一个十进制的正整数完全由0和3组成,这个数可不可以是2018的倍数?
分析:
设此数为K, K|2018
2018=2*1009 (1009为素数)
则有K|1009, K|2
易知K的各位之和为3的倍数, K|3
只需要找到满足为1009的倍数的k=K/3
若此数非2的倍数, 乘10即可
解法1
费马小定理
a为任意整数, p为素数
\(a^{p}≡a \mod{p}\)
特殊的, 若gcd(a,p)=1
\(a^{p-1}≡1 \mod{p}\)
\(10^{1009-1}≡1 \mod{1009}\)
\(10^{1009-1}-1 ≡0\mod{1009}\)
\(K=\cfrac{10^{1009-1}-1}{3}\)
K的每一位都是3, 但K并不被2整除, 故10K即为我们要找的数字
解法2
构造数列1,11,111,1111……
易知其有无穷项
但其对1009取模只有有限项, 由鸽巢原理, 必有 am - an ≡ 0 mod 1009
am - an 必定为前m-n位为1, 后n位为0的形式, 所以一定是2的倍数
K = 3( am - an ), 即为所求
1 | K=3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333330 |
十进制下只有253位, 相较费马小定理已经小了太多了
这种数列未考虑项中各位有0的情况, 但如果考虑的话, 又可能造成相减后未必仍符合要求的问题
解法3
\({k}\equiv{m} \mod{ 1009}\)
对于每一个m, 总能找到最小的kmin,
而后我们爆破a = int( bin(i)[2:] + str(kmin) ) , 寻找模1009余m的最小a
3(a-kmin)即为所求
在这里令m = 1
爆破得a = 100100011111111
K = 3(a-kmin) = 300300033333330 = 297621440370*1009
而100100011111111=int(bin(18686)[2:]+str(kmin))
可以爆破一下, 寻找更小的答案
1 | for i in range(1,18687): |
运行结果显示不存在更小的答案了