杭电 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;
}


 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值