HDOJ 1014 Uniform Generator 解题报告
Uniform Generator
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 12638 Accepted Submission(s): 4969
Problem Description
Computer simulations often require random numbers. One way to generate pseudo-random numbers is via a function of the form
seed(x+1) = [seed(x) + STEP] % MOD
where '%' is the modulus operator.
Such a function will generate pseudo-random numbers (seed) between 0 and MOD-1. One problem with functions of this form is that they will always generate the same pattern over and over. In order to minimize this effect, selecting the STEP and MOD values carefully can result in a uniform distribution of all values between (and including) 0 and MOD-1.
For example, if STEP = 3 and MOD = 5, the function will generate the series of pseudo-random numbers 0, 3, 1, 4, 2 in a repeating cycle. In this example, all of the numbers between and including 0 and MOD-1 will be generated every MOD iterations of the function. Note that by the nature of the function to generate the same seed(x+1) every time seed(x) occurs means that if a function will generate all the numbers between 0 and MOD-1, it will generate pseudo-random numbers uniformly with every MOD iterations.
If STEP = 15 and MOD = 20, the function generates the series 0, 15, 10, 5 (or any other repeating series if the initial seed is other than 0). This is a poor selection of STEP and MOD because no initial seed will generate all of the numbers from 0 and MOD-1.
Your program will determine if choices of STEP and MOD will generate a uniform distribution of pseudo-random numbers.
seed(x+1) = [seed(x) + STEP] % MOD
where '%' is the modulus operator.
Such a function will generate pseudo-random numbers (seed) between 0 and MOD-1. One problem with functions of this form is that they will always generate the same pattern over and over. In order to minimize this effect, selecting the STEP and MOD values carefully can result in a uniform distribution of all values between (and including) 0 and MOD-1.
For example, if STEP = 3 and MOD = 5, the function will generate the series of pseudo-random numbers 0, 3, 1, 4, 2 in a repeating cycle. In this example, all of the numbers between and including 0 and MOD-1 will be generated every MOD iterations of the function. Note that by the nature of the function to generate the same seed(x+1) every time seed(x) occurs means that if a function will generate all the numbers between 0 and MOD-1, it will generate pseudo-random numbers uniformly with every MOD iterations.
If STEP = 15 and MOD = 20, the function generates the series 0, 15, 10, 5 (or any other repeating series if the initial seed is other than 0). This is a poor selection of STEP and MOD because no initial seed will generate all of the numbers from 0 and MOD-1.
Your program will determine if choices of STEP and MOD will generate a uniform distribution of pseudo-random numbers.
Input
Each line of input will contain a pair of integers for STEP and MOD in that order (1 <= STEP, MOD <= 100000).
Output
For
each line of input, your program should print the STEP value right-
justified in columns 1 through 10, the MOD value right-justified in
columns 11 through 20 and either "Good Choice" or "Bad Choice"
left-justified starting in column 25. The "Good Choice" message should
be printed when the selection of STEP and MOD will generate all the
numbers between and including 0 and MOD-1 when MOD numbers are
generated. Otherwise, your program should print the message "Bad
Choice". After each output test set, your program should print exactly
one blank line.
Sample Input
3 5
15 20
63923 99999
Sample Output
3 5 Good Choice
15 20 Bad Choice
63923 99999 Good Choice
Source
Recommend
JGShining
这道题目读题目就花了好久,真心英语太烂,,看不懂额,,
后来慢慢算是理解题意了。
算是明白了题目的意思。。。。
写代码写着写着,
有一种思路,但是死活通不过,,不知道为什么
下面是另外一种做法,就是最大公约数为1
看到网上说 这道题目就是求最大公约数,
公约数为1,
就为Good 否则则为Bad,
但是没有给出解释,我将做出解释,
其实是这样的。
如果是step<mod,
第一次计算的时候结果为step本身,
第二次为2*step,第三次是3*step,
一直到(k-1)*step,此时下一次计算就为 (k*step)%mod=0,
得不到题意的要求。 因此只能是最大公约数为1
其实,这个题想通了就很简单了,还是数论里面的群的概念,就是加法群的生成群啊,打着随机数的幌子而已。由于又没有限定种子,限定
对答案也没有影响,假设种子是0,那么数列可以表示为a*step,数列要能够生成0 - mod-1中所有的数字,那么就有a*step = b % mod
(0<=b<mod)。
哈哈,上面那个式子就是a*x=b%n这个线性同余方程了,只是有很多b了。要方程有解,不是需要满足条件gcd(a,n)|b么,意思b是
gcd(a,n)的整数倍了。但是0<=b<n啊,b会是1了,那么gcd(a,n)一定是1了哦。那么直接判断gcd(step,mod)是否为1就行了,哈哈。
关于线性同余方程a*x=b%n,要有解的条件gcd(a,n)|b的解释,还是参看算法导论或者其它资料吧。。。
对答案也没有影响,假设种子是0,那么数列可以表示为a*step,数列要能够生成0 - mod-1中所有的数字,那么就有a*step = b % mod
(0<=b<mod)。
哈哈,上面那个式子就是a*x=b%n这个线性同余方程了,只是有很多b了。要方程有解,不是需要满足条件gcd(a,n)|b么,意思b是
gcd(a,n)的整数倍了。但是0<=b<n啊,b会是1了,那么gcd(a,n)一定是1了哦。那么直接判断gcd(step,mod)是否为1就行了,哈哈。
关于线性同余方程a*x=b%n,要有解的条件gcd(a,n)|b的解释,还是参看算法导论或者其它资料吧。。。
WA代码
1 #include<stdio.h> 2 int main() 3 { 4 int a[100001]={0}; 5 int i,flag=0; 6 int temp=0; 7 int step, mod; 8 while(scanf("%d%d", &step, &mod)!=EOF) 9 { 10 for(i=0;i<mod;i++) 11 { 12 temp=(temp+step)%mod; //感觉我自己的这个代码是烂代码。 13 a[temp]++; 14 } 15 for(i=0;i<mod;i++) 16 { 17 if(a[i]==0) 18 { 19 flag=1; 20 printf("%10.d%10.d Bad Choice\n", step, mod); 21 break; 22 } 23 } 24 if(flag!=1) 25 printf("%10.d%10.d Good Choice\n", step, mod); 26 } 27 return 0; 28 }
最后看了看其他人的代码。
知道了一个我觉得挺好的算法。
总算是AC了
#include<stdio.h> int main() { int a[100000]={0}; int step, mod, i; while(scanf("%d%d", &step, &mod)!=EOF) { i=0; do { a[i+1]=(a[i]+step)%mod; i++; //a[0]默认为0,这里i++之后,后面的while()里的a[i]就不是a[0]了 }while(a[i]!=0); if(i==mod) //说明没有重复,也就是0到MOD-1的数都在随机数里面了。 printf("%10d%10d Good Choice\n\n", step, mod); else printf("%10d%10d Bad Choice\n\n", step, mod); } return 0; }
#include<stdio.h> int main() { int a,b; int gcd(int a,int b); while(scanf("%d%d",&a,&b)!=EOF) { if(gcd(a,b)!=1) printf("%10d%10d Bad Choice\n\n",a,b); else printf("%10d%10d Good Choice\n\n",a,b); } } int gcd(int a,int b) //很标准的辗转相除法 { int t; while(b>0) { t=a%b; a=b; b=t; } return (a); }