東京大学 情報理工学系研究科 創造情報学専攻 2015年2月実施 プログラミング
Author
Description
Official examination, archived Japanese PDF.
(1) The following function is a function often used as a simple random number generator.
where is a non-negative integer and denotes a modulus operator (the remainder). Write a program that computes for given . Then print the value of by using this program.
(2) Write a program that counts the number of such that and is an even number.
(3) Write a program that counts the number of such that is an odd number, , and is an even number.
(4) Write a program that prints the value of .
(5) Write a program that computes the following function where is a non-negative integer:
Then run the program to print the values of and .
(6) Write a program that computes the smallest positive integer such that for any non-negative integer .
(7) Write a program that computes the smallest positive integer such that for any non-negative integer . Write on the answer sheet why the program correctly computes . is a function defined as follows:
题目描述
-
对非负整数 ,定义常用作简单伪随机数发生器的递推函数
其中 表示取余。编写程序计算给定 的 ,并输出 。
-
统计满足 且 为偶数的 的个数。
-
统计满足 、 为奇数且 为偶数的 的个数。
-
编写程序输出 。
-
对非负整数 ,定义
编写程序计算 ,并运行输出 与 。
-
编写程序求最小正整数 ,使对任意非负整数 均有 。
-
定义
编写程序求使任意非负整数 均满足 的最小正整数 ,并在答题纸上说明程序为何能正确求得该 。
Kai
(1) Iterative recurrence
Start from and apply the recurrence times. After iteration , , so the result is . This uses time and storage without recursion depth proportional to .
(2) and (3) Even values
Modulo 2, both constants are odd, so . Since is odd, is even exactly when is odd. Among the non-negative indices , there are 50 odd indices. Thus both requested counts are
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:
(5) The second generator
Use 64-bit integer arithmetic for the multiplication before reducing modulo . Since , the largest intermediate product plus increment is less than , within 64-bit range. Computing the multiplication with a 32-bit signed integer could overflow before the modulus is taken.
(6) Period of
The multiplier is odd, hence invertible modulo . Therefore 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 steps, determinism implies for every . No smaller positive period is possible, since such a period would already return to .
The program gives
(7) Period of the low ten bits
Reduction modulo commutes with multiplication, addition and reduction modulo . Hence itself satisfies
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 :
The powers of two can also be derived without enumerating the cycles. For any positive integer ,
before taking the modulus. Here and is odd, so the first factor is odd. Let . The identity shows that each doubling adds exactly one factor of 2, since . If with odd, is a sum of odd terms and is odd. Thus has exactly as many factors of 2 as . It follows that exactly when divides , proving the periods for both and .
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 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