现在的位置: 首页 > 综合 > 正文

2013.3.31百度之星,线性同余发生器 求序列周期(2)—给出一个正解

2013年12月21日 ⁄ 综合 ⁄ 共 3349字 ⁄ 字号 评论关闭

声明:这篇博文主要整理自百度之星大赛讨论区goodbyeworld的留言,有些地方我做了些修改,也加入了不少对细节的证明。

正文:

“2013.3.31百度之星,线性同余发生器 求序列周期(1)”中最后的问题主要集中在当q是奇数的时候,生成的序列具有什么样的周期,以及从哪里开始进入周期的循环。

针对 mi+1= (q2mi
+ 1) mod 2n
这个发生器已经找到它的周期了。

先给出模运算的几个性质

(a + b) % p = (a % p + b % p) % p (1)
(a - b) % p = (a % p - b % p) % p (2)
(a * b) % p = (a % p * b % p) % p (3)
((a +b)% p * c) % p = ((a * c) % p + (b * c) % p) % p (4)分配率
对于不经常用这些性质的人来说,即便是这几个性质也有些陌生。
然后,证明如下的一些引理
1.奇数mod偶数=奇数,偶数mod偶数=偶数
这个说明起来很简单。把上面的表述写成(2p+1)%(2q)和(2p)%(2q)
对于(2p+1)%(2q),若是2p+1<2q显然成立。若是2p+1>2q,(2p+1)%(2q)=2p+1-k(2q)=2(p-kq)+1自然是奇数。对于(2p)%(2q)同样可以写成这个形式加以说明。
简单的证明了几个模运算的东西,发现证明时运用模运算的定义很强大。
2.x含有因子2的数目为k,k<=n,y=x%2^n,求证y含有因子2的数目也为k。
证明:
如果x<=2^n,y=x,显然成立;
接下来只考虑x>2^n,
把x写成这个形式:x=p*2^k,求余的过程可以表示成
p*2^k-c*2^n=b*2^a,其中p,b不含有因子2,c可能含有因子2,k<=n,我们想证明a=k。
整理一下,2^k*[p-c*2^(n-k)]=b*2^a。
先证明p-c*2^(n-k)不含因子2,假设它含有因子2,它可以写成p-c*2^(n-k)=2^d,
p=2^d+c*2^(n-k),2^d+c*2^(n-k)肯定可以提取因子2,这与p不含有因子2矛盾,所以p-c*2^(n-k)不含因子2。
所以a=k肯定成立,不然的话与2^k*[p-c*2^(n-k)]=b*2^a矛盾(相等含有因子2的数目肯定相等)。over!
3.奇数的平方模4余1
(2n+1)^2=4n(n+1)+1,很明显了。
-------------------------------------------------------------------------------------------------------------------------------割-----------------------------------------------------------------------------------------------------

我们设c=0,所以序列从X(0)=0启动,X(k+1)=(q^2*X(k)+1)mod(2^n)

应用性质(1)(4)可以得到X(k)=sum(q^(2i),i=0..k-1)%(2^n),即X(k)=[1+q^2+q^4+...+q^(2(k-1))]%(2^n)

1,q^2,q^4,...,q^(2(k-1))的每一项都是奇数,显然

1
q^2+1
q^4+q^2+1
q^6+q^4+q^2+1

.... ....

是奇偶交替的。

又因为“奇数mod偶数=奇数,偶数mod偶数=偶数”,所以

x1=1%2^n
x2=(q^2+1)%2^n
x3=(q^4+q^2+1)%2^n
x4=(q^6+q^4+q^2+1)%2^n
... ....

也是奇偶交替的。即X(0),X(1),X(2),X(3),......也是奇偶交替的。

S[1]={X(1),X(3),X(5)....}是奇数数列
X(2k)

=[1+q^2+q^4+...+q^(2(k-1))+...+q^(2(2k-1))]%(2^n)

=[1+q^2+q^4+...+q^(2(k-1))(1+q^(2k))]%(2^n)  (提取公因子)

=[X(k)*(1+q^(2k)) ]mod(2^n)(反复应用性质3)

因为'奇数的平方模4余1',q^(2k)是奇数,q^(2k)%4=1,所以1+q^(2k)可以被2整除,但是不能被4整除。(同样可以用模运算的定义说明)
S[2]={X(2),X(6),X(10),X(14)...}= S[1] *{1+q^2,1+q^6,1+q^10,....}mod 2^n,每一项可以被2整除,但不被4整除  (引理2.)
S[4]={X(4),X(12),X(20),X(28),...}=S[2]*{1+q^4,1+q^12,1+q^20,....} mod 2^n,每一项可以被4整除,但不被8整除  (引理2.)

归纳S[8],S[16],...S[2^n]都是类似的性质,即S[2^t]中的元素含有因子2的数目为t。这个规律很好,X(1),....X((2^n)-1)都含有因子2,不为0,直到S[2^n]={X(2^n)}=0。

除了X(0)=0,下一个X(k)=0出现是X(2^n) =0. 所以2^n是一个周期。

假设存在比2^n更小的周期,那么存在0<=a<b 且b-a<2^n,并 有X(a)=X(b),
0=X(b)-X(a)

=sum(q^(2i),i=a,a+1,...,b-1)mod 2^n

= q^(2a)*sum(q^(2i),i=0..b-a-1) mod(2^n)
=q^(2a)*X(b-a)mod 2^n.(反复应用性质3)

 q^(2a)是奇数,X(b-a)=0(若不等于0,q^(2a)*X(b-a)mod 2^n不可能为0,因为q^(2a)*X(b-a)这个里面含有因子2的数目不会大于等于n的) , b-a<2^n,这与 X(2^n)=0 才是下一个0项矛盾。
所以最小周期就是2^n

X(k)的可能的取值只有0..2^n-1,周期是2^n,所以X[0..(2^n-1)]取遍[0..(2^n-1)],达到满周期。

 

现在解决这个题目一个自然的想法就是只要找到 c,x距离0的位置a,b,那么a,b之间的距离就是答案了。也就是任意给定一个数y,确定这个数需要迭代几步会到达0.

我们可以先确定y最大被2的几次幂整除 ,假设是t。

借助上面的S[1],S[2],S[4],S[8]...数列,知道y在S[2^t]里。y迭代2^t步后得到z,z就至少在S[2^(t+1)],或者更后的S[2^(t+??)]里。

对于上面这句话,这里给出一个证明。假设y开始的位置为i(我们并不知道i的具体数值),i=2^t*p,p中不含有因子2为奇数。

i+2^t=2^p+2^t

=2^t(p+1)=2^(t+??)q

最后的推导表示从p+1中尽可能多的提取因子2(至少含有一个)。

然后再判断Z含有的因子2的数目,如此循环直到迭代到0出现。

伪代码写出来如下
cnt = 0
while h ==0
     L   :=Lowbit (h) //用lowbit 运算得出最大被2的多少次幂整除。
     h   := (h * ((q^2)^(L))+ (1+q^2+q^4 + ... +(q^2)^(L-1)))mod (2^n) //h迭代L步,需要倍增快速计算
     cnt:=cnt + L  //计数迭代的总布数

cnt就是需要找的迭代步数。

--------------------------------------------------------------------------------------------------------------------割----------------------------------------------------------------------------------------------------------------

讨论:

1.我们挖掘S[1],S[2],S[4],S[8]...数列的规律一方面发现了满周期,最主要的是为了后面的快速迭代(没感觉出来这个能快多少?存储1+q^2+q^4 + ...这些值 迭代更快),其实发现满周期后一步步迭代不知道能不能AC。

2.拓展一下,对于其他形式的发生式怎么去发现周期规律呢?

抱歉!评论已关闭.