跳到主要内容

東京大学 情報理工学系研究科 創造情報学専攻 2015年2月実施 プログラミング

Author

itsuitsuki

Description

Official examination, archived Japanese PDF.

(1) The following function ff is a function often used as a simple random number generator.

f(n)={1if n<1,(161×f(n1)+2457)mod224otherwise.f(n) = \begin{cases} 1 & \text{if } n < 1, \\ (161 \times f(n-1) + 2457) \mod 2^{24} & \text{otherwise}. \end{cases}

where nn is a non-negative integer and modmod denotes a modulus operator (the remainder). Write a program that computes f(n)f(n) for given nn. Then print the value of f(100)f(100) by using this program.

(2) Write a program that counts the number of ii such that i<100i < 100 and f(i)f(i) is an even number.

(3) Write a program that counts the number of ii such that ii is an odd number, i<100i < 100, and f(i)f(i) is an even number.

(4) Write a program that prints the value of f(1000000)f(1000000).

(5) Write a program that computes the following function gg where nn is a non-negative integer:

g(n)={1if n<1,(1103515245×g(n1)+12345)mod226otherwise.g(n) = \begin{cases} 1 & \text{if } n < 1, \\ (1103515245 \times g(n-1) + 12345) \mod 2^{26} & \text{otherwise}. \end{cases}

Then run the program to print the values of g(2)g(2) and g(3)g(3).

(6) Write a program that computes the smallest positive integer kk such that g(n+k)=g(n)g(n + k) = g(n) for any non-negative integer nn.

(7) Write a program that computes the smallest positive integer kk such that h(n+k)=h(n)h(n+k) = h(n) for any non-negative integer nn. Write on the answer sheet why the program correctly computes kk. hh is a function defined as follows:

h(n)=g(n)mod210h(n) = g(n) \mod 2^{10}

题目描述

  1. 对非负整数 nn,定义常用作简单伪随机数发生器的递推函数

    f(n)={1,n<1,(161f(n1)+2457)mod224,n1.f(n)= \begin{cases} 1,&n<1,\\ (161f(n-1)+2457)\bmod2^{24},&n\ge1. \end{cases}

    其中 mod\bmod 表示取余。编写程序计算给定 nnf(n)f(n),并输出 f(100)f(100)

  2. 统计满足 i<100i<100f(i)f(i) 为偶数的 ii 的个数。

  3. 统计满足 i<100i<100ii 为奇数且 f(i)f(i) 为偶数的 ii 的个数。

  4. 编写程序输出 f(1000000)f(1000000)

  5. 对非负整数 nn,定义

    g(n)={1,n<1,(1103515245g(n1)+12345)mod226,n1.g(n)= \begin{cases} 1,&n<1,\\ (1103515245g(n-1)+12345)\bmod2^{26},&n\ge1. \end{cases}

    编写程序计算 gg,并运行输出 g(2)g(2)g(3)g(3)

  6. 编写程序求最小正整数 kk,使对任意非负整数 nn 均有 g(n+k)=g(n)g(n+k)=g(n)

  7. 定义

    h(n)=g(n)mod210.h(n)=g(n)\bmod2^{10}.

    编写程序求使任意非负整数 nn 均满足 h(n+k)=h(n)h(n+k)=h(n) 的最小正整数 kk,并在答题纸上说明程序为何能正确求得该 kk

Kai

(1) Iterative recurrence

Start from x=1=f(0)x=1=f(0) and apply the recurrence nn times. After iteration ii, x=f(i)x=f(i), so the result is f(n)f(n). This uses O(n)O(n) time and O(1)O(1) storage without recursion depth proportional to nn.

f(100)=7104005.\boxed{f(100)=7104005.}

(2) and (3) Even values

Modulo 2, both constants are odd, so f(i)f(i1)+1(mod2)f(i)\equiv f(i-1)+1\pmod2. Since f(0)f(0) is odd, f(i)f(i) is even exactly when ii is odd. Among the non-negative indices 0i<1000\le i<100, there are 50 odd indices. Thus both requested counts are

50.\boxed{50.}

The loop below counts the current value before advancing, so its indices are precisely 0 through 99.

(4) One million updates

Apply the same constant-space loop:

f(1000000)=11329.\boxed{f(1000000)=11329.}

(5) The second generator

Use 64-bit integer arithmetic for the multiplication before reducing modulo 2262^{26}. Since 0g(n)<2260\le g(n)<2^{26}, the largest intermediate product plus increment is less than 7.5×10167.5\times10^{16}, within 64-bit range. Computing the multiplication with a 32-bit signed integer could overflow before the modulus is taken.

g(2)=41857255,g(3)=58844308.\boxed{g(2)=41857255,\qquad g(3)=58844308.}

(6) Period of gg

The multiplier a=1103515245a=1103515245 is odd, hence invertible modulo 2262^{26}. Therefore T(x)=ax+12345(mod226)T(x)=ax+12345\pmod{2^{26}} is a permutation of the finite state space. Starting from 1, it lies on a cycle from the beginning. Iterate until the first return to 1; if it occurs after kk steps, determinism implies g(n+k)=g(n)g(n+k)=g(n) for every nn. No smaller positive period is possible, since such a period would already return g(k)g(k) to g(0)=1g(0)=1.

The program gives

kg=226=67108864.\boxed{k_g=2^{26}=67108864.}

(7) Period of the low ten bits

Reduction modulo 2102^{10} commutes with multiplication, addition and reduction modulo 2262^{26}. Hence hh itself satisfies

h(0)=1,h(n+1)=(1103515245h(n)+12345)mod210.h(0)=1,\qquad h(n+1)=(1103515245h(n)+12345)\bmod2^{10}.

Run the first-return algorithm directly on these 1024 states. Its transition is again a permutation, so the same proof establishes that its first return is the smallest period valid for all nn:

kh=210=1024.\boxed{k_h=2^{10}=1024.}

The powers of two can also be derived without enumerating the cycles. For any positive integer rr,

Tr(x)x=((a1)x+c)j=0r1ajT^r(x)-x=((a-1)x+c)\sum_{j=0}^{r-1}a^j

before taking the modulus. Here a1(mod4)a\equiv1\pmod4 and cc is odd, so the first factor is odd. Let Sr=j=0r1ajS_r=\sum_{j=0}^{r-1}a^j. The identity S2r=Sr(1+ar)S_{2r}=S_r(1+a^r) shows that each doubling adds exactly one factor of 2, since 1+ar2(mod4)1+a^r\equiv2\pmod4. If r=2jmr=2^j m with mm odd, Sr/S2jS_r/S_{2^j} is a sum of mm odd terms and is odd. Thus SrS_r has exactly as many factors of 2 as rr. It follows that Tr(x)x(mod2b)T^r(x)\equiv x\pmod{2^b} exactly when 2b2^b divides rr, proving the periods for both b=26b=26 and b=10b=10.

Complete C program

All products in this program stay within uint64_t. The state is reduced by a bit mask, which is the remainder modulo 2b2^b for these non-negative integers.

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>

static uint64_t advance(uint64_t x, uint64_t a, uint64_t c, unsigned bits) {
return (a*x+c) & ((UINT64_C(1)<<bits)-1);
}

static uint64_t value(uint64_t n, uint64_t a, uint64_t c, unsigned bits) {
uint64_t x=1;
for (uint64_t i=0; i<n; ++i) x=advance(x,a,c,bits);
return x;
}

static uint64_t period(uint64_t a, uint64_t c, unsigned bits) {
uint64_t x=1, k=0;
do {
x=advance(x,a,c,bits);
++k;
} while (x!=1);
return k;
}

int main(void) {
uint64_t x=1, even=0, odd_index_even=0;
for (uint64_t i=0; i<100; ++i) {
if ((x&1)==0) {
++even;
if (i&1) ++odd_index_even;
}
x=advance(x,161,2457,24);
}
printf("f(100)=%" PRIu64 "\n",x);
printf("even=%" PRIu64 "\nodd-index-even=%" PRIu64 "\n",even,odd_index_even);
printf("f(1000000)=%" PRIu64 "\n",value(1000000,161,2457,24));
printf("g(2)=%" PRIu64 "\ng(3)=%" PRIu64 "\n",
value(2,1103515245,12345,26),value(3,1103515245,12345,26));
printf("g-period=%" PRIu64 "\n",period(1103515245,12345,26));
printf("h-period=%" PRIu64 "\n",period(1103515245,12345,10));
return 0;
}

Output:

f(100)=7104005
even=50
odd-index-even=50
f(1000000)=11329
g(2)=41857255
g(3)=58844308
g-period=67108864
h-period=1024