杭电 acm 1014 Uniform Generator
题意: 随机数 seed(x+1) = [seed(x) + STEP] % MOD
如果 STEP = 3,MOD = 5 循环节 0,3,1,4,2,正好满足了随机数0~4随机循环,说明这个选择为 Good Choice
如果 STEP = 15,MOD = 30 循环节 0, 15, 10, 5,没有满足随机数0~29循环,说明这个选择为Bad Choice
现在给你 STEP 和 MOD 判断是 Good Choice 或者Bad Choice
第一种解法 暴力
思路:以为在0~~~MOD-1的随机数,所以只要循环MOD-1次就可以了,如果中间重复,就是Bad Choice,如果没出现说明Good Choice
因为 有一个数重复,那么必然后面的数都重复,所以只要循环MOD-1。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int visit[100005];
int main()
{
int sept,mod;
while(scanf("%d%d",&sept,&mod) != EOF)
{
int flag = 0,n = 0;
memset(visit,0,sizeof(visit));
for(int i = 1; i <= mod; i++)
{
n = (n + sept) % mod;
if(visit[n])
{
flag = 1;
break;
}
else
{
visit[n] = 1;
}
}
if(flag)
printf("%10d%10d Bad Choice\n\n",sept,mod);
else
printf("%10d%10d Good Choice\n\n",sept,mod);
}
return 0;
}
思路二:数论
seed(x+1) = [seed(x) + STEP] % MOD,他要出现k的循环节所以 seed[k] = (seed[0] + STEP*k) %MOD = seed[0],
seed[0] = 0,所以seed[k] =STEP*k %MOD = 0,说明seed[k] =STEP*k = n * MOD,
因为 要出现MOD的循环节 所以 k >= MOD 所以 STEP * MOD = n * MOD,n = SEPT,结果他们是互质的才能是这样
所以 gcd(SEPT,MOD) = = 1 是 Good Choice 否则 Bed Choice
拓展:求其循环节长度
如果他们互质,他们的循环节为MOD。
如果他们有公因数,因为STEP*k = n * MOD,n最小取1 原式 = STEP*k = MOD,k为循环节长度,k = MOD / STEP
另一种解释:
看到网上说 这道题目就是求最大公约数,公约数为1,就为Good 否则则为Bad,但是没有给出解释,我将做出解释,其实是这样的。假设 step和 mod有最大公约数 k (k>1),如果是step>mod 那么在第一次计算的时候,会step%mod=0,从而这个组永远就是0,显然与题意不符,如果是step<mod,第一次计算的时候结果为step本身,第二次为2*step,第三次是3*step,一直到(k-1)*step,此时下一次计算就为
(k*step)%mod=0, 得不到题意的要求。 因此只能是最大公约数为1
#include <stdio.h>
#include <string.h>
#include <math.h>
int main()
{
int gcd(int a,int b);
int i,j,n,m,s,t;
int a,b;
while(scanf("%d %d",&a,&b)!=EOF)
{
t=gcd(a,b);
printf("%10d%10d ",a,b);
if(t==1)
{
printf("Good Choice\n");
}else
{
printf("Bad Choice\n");
}
printf("\n");
}
return 0;
}
int gcd(int a,int b)
{
return b? gcd(b,a%b):a;
}
解法三:
/*
Author:snowflake
Time:2012/5/13
Desc:Water...
*/
/*
题目的大意:就是给定两个数step, mod然后利用给定的公式求随机数,保证从0到mod减1范围内
每一个数都出现一次。这样就均等分布了。就打印Good否则就Bad
就是枚举产生随机数,然后排序在比对,注意下输出的格式就OK了。
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAX 100000 + 10
int random[MAX];
int main()
{
int step, mod;
int i;
bool flag;
while(cin >> step >> mod)
{
flag = true;
random[0] = 0;
//第一个数字永远是0
for(i = 1; i <= mod - 1; i++)
{
random[i]= (random[i - 1] + step) % mod;
}
sort(random, random + mod);
for(i = 0; i < mod; i++)
{
if(random[i] != i)
flag = false;
}
if(flag)
printf("%10d%10d Good Choice\n\n",step, mod);
else
printf("%10d%10d Bad Choice\n\n",step, mod);
}
return 0;
}