本文参考资料:http://hi.baidu.com/bnjyjncwbdbjnzr/item/1f997cfdd225d5d143c36a58

题意:一个生成随机数的函数,

Seed[x+1] = ( seed[x] + STEP ) % MOD

输入step和mod,问能否生成0~MOD-1之间所有的数,是Good Choice,否则Bad Choice

题意其实就是:给出S和M,求0*S%M,1*S%M,2*S%M......(M-1)*S%M能否组成一个集合包含0.1.。。。M-1;(这个是原题意改造而来);

算法:判断两个数是否互质;or 暴力解决

其实暴力完全可以解决这个问题(⊙﹏⊙b),只是其中用数学方法更加高效,巧妙;

下面证明“如果SM互质则满足题意”:

设G=gcd(S,M);则S=A*G,M=B*G;

另设X=K*S%M=K*S-T*M(T为整数,满足X属于0到M-1。其实就是说T是K*S除以M的商。);

X=K*A*G-T*B*G;因此取余后的整数一定是G的倍数。

所以,上述要求证明的命题其实就是要证明:G只能取1才能满足条件;

(个人感觉上述论证就是废话呵呵——S和M互质不就是gcd(S,M)==1吗?)

(下面继续刚才的证明)

充分性的证明:(即当S与M互质,则0到M-1的S倍对M取余一定能遍历0到M-1)

只需证明的是,该余数中两两之间互不相等;

假设k*S和b*S对M取余相等(k和b∈[0,M),并且k和b不等);

则k*S=q1*M+r≡q2*M+r=b*S     <==>      (k-b)*S=M*(q1-q2);

因为题设S与M互质,再由上式子可得M|(k-b),这与k和b∈[0,M),并且k和b不等矛盾;

因此题目命题得证。

另外,偶然看到一个很牛叉的辗转相除法;

int gcd(int a,int b)

{

while(b) b^=a^=b^=a%=b;

return a;

}

此代码,很好很强大;把涉及位运算的交换的程序加入,便到得这段简洁高效的代码;

注:A和B;经过A^=B^=A^=B,结果就得到A和B的交换;

 #include<stdio.h>
long gcd(long a,long b);
int main()
{
long step,mod;
while(scanf("%ld%ld",&step,&mod)!=EOF)
{
if(gcd(step,mod)==) printf("%10d%10d Good Choice\n\n",step,mod);
else printf("%10d%10d Bad Choice\n\n",step,mod);
}
return ;
}
long gcd(long a,long b)
{
long c;
if(b==) return a;
c=a%b;
while(c)
{
a=b;
b=c;
c=a%b;
}
return b;
}

下面是其他网友对该问题的论述:(感觉没有上面的讲的清楚,可以直接忽略)

以数论的观点解释 poj1597 && 更相减损术

http://blog.163.com/jiazheng2222@126/blog/static/1696323832009513104450808/

可以想象成有一个人从起点0处绕着一个圈长为mod个单位“跳步”,每跳一次必须跳step个单位(也就是可不能出现在i*step<pos<(i+1)*step的位置),而至少跳mod次恰好回到起点的话,就是Good Choice,如果在第mod次前就恰好到达起点则为Bad Choice

而我们知道,回到起点把所需的最短时间即是step和mod的最小公倍数,而若为Good Choice,显然最短时间又等于step*mod,由数论的知识gcd(step,mod)=step*mod/(step和mod的最小公倍数)=1

bool check(long step,long mod)
{
    long m=step>mod?step:mod;
    long n=step>mod?mod:step;
    long q=1;

while(q!=0)
    {
        q=m-n;
        m=n>q?n:q;
        n=n>q?q:n;

}
    if(m==1)
        return true;
    else
        return false;
}

http://hi.baidu.com/sjzezoi/item/6a3a71ccab9fee32b67a24fa

题意:一个生成随机数的函数,

Seed[x+1] = ( seed[x] + STEP ) % MOD

问能不能生成0~MOD-1之间所有的数,是Good Choice,否则Bad Choice

此题可以暴力模拟,但正解应该是gcd(STEP,MOD)==1

设G=gcd(a,b),于是有a=A*G,b=B*G(1<=A,B,gcd(A,B)=1) 对于a的多次加可以看成K*a(1<=k),转化成(K*a)%b的所有结果能否表示成0..b-1中的所有数,假(K*a)%b=M,M=K*a-W*b(W为使M>0的最大整数),M=K*A*G-W*B*G M%G==0,既结果是G的倍数,如果想取得0..b-1中的所有数,那么必须G=1才可能..

(代码仅供参考和学习,请不要直接粘贴刷AC数,期待你写出更好的代码)贡献一次PE

暴力:

#include<cstdio>

#include<cstring>

int a,b;

bool vis[100010];

int main()

{

while(scanf("%d%d",&a,&b)+1)

{

memset(vis,0,sizeof vis);

int cnt=0,now=0;

while(cnt<b)

{

if(vis[now]) break;

vis[now]=1;

now=(now+a)%b;

cnt++;

}

if(cnt==b) printf("%10d%10d    Good Choice\n\n",a,b);

else printf("%10d%10d    Bad Choice\n\n",a,b);

}

return 0;

}

正解:

#include<cstdio>

int a,b;

inline int gcd(int x,int y)

{

if(!y) return x;

return gcd(y,x%y);

}

int main()

{

while(scanf("%d%d",&a,&b)==1)

{

if(gcd(a,b)==1) printf("%10d%10d    Good Choice\n\n",a,b);

else printf("%10d%10d    Bad Choice\n\n",a,b);

}

return 0;

}

http://hi.baidu.com/zhuangxie1013/item/cc5a130b05e77ad573e676b0

这题其实是道数论题,但我把它当作模拟题来做了,虽然做出来了,但所用的空间和时间也大的吓人,此题输出时需要注意:输出格式为printf("%10d%10d    Bad
Choice\n\n",step,mod);即第二个数和Bad Choice之间有4个空格,下面是我模拟出来的程序:

#include<iostream>
#include<set>
#include<algorithm>
#include<cstdlib>
using namespace std;

int main()
{
int step,mod,i,temp;
set<int>s;
while(scanf("%d %d",&step,&mod)!=EOF)
{
   temp=0;
   s.insert(temp);
   for(i=1;i<mod;i++)
   {
    temp=(temp+step)%mod;
    s.insert(temp);
   
if(s.size()!=(i+1))                                                                
//出现重复元素
    {
     printf("%10d%10d    Bad
Choice\n\n",step,mod);
     break;
    }

}
   temp=(temp+step)%mod;
   if(temp==0&&s.size()==mod)
    printf("%10d%10d    Good
Choice\n\n",step,mod);
     s.clear();
}
system("pause");
return 0;
}

看了别人的方法,讲的都是数论,所以将其转载:

题目的意思就是一个生成随机数的函数,

Seed[x+1] = ( seed[x]
+ STEP ) % MOD

其中seed就是我们生成出来的随机数,至于seed[0]是哪个数并不重要,后面会证明。STEP就是我们每次往前一个所加的值,再module上MOD得到下一个随机数。

判断这个随机生成函数的好坏的依据是如果能够产生0~MOD-1内的所有数,就是一个好的,否则坏。

我们知道了同余的特性,便可以假设在k步之后,生成的seed[k] = seed[0],所以由此有

Seed[k] = ( seed[0]
+ STEP*k ) % MOD

那么,

STEP * k = MOD

而我们如果要生产MOD个数,必须使k≥MOD,而且k不可能大于MOD,因为这个条件下生成的数又开始重复,所以k=MOD;在前面的条件下,如果STEP和MOD有大于1的公约数例如d,那么会有STEP*(k/d) = MOD,这就是一个循环了,只会产生k/d<MOD个随机数。

结论:iff gcd(STEP, MOD) == 1, good choice

poj 1597 Uniform Generator【生成指定范围内所有随机数】的更多相关文章

  1. JS生成指定范围内的随机数(支持随机小数)

    直接需要函数的话,直接到文章的最后面找. ============================================================= 转载:https://www.cn ...

  2. 【转载】C#使用Random类来生成指定范围内的随机数

    C#的程序应用的开发中,可以使用Random随机数类的对象来生成相应的随机数,通过Random随机数对象生成随机数的时候,支持设置随机数的最小值和最大值,例如可以指定生成1到1000范围内的随机数.R ...

  3. 关于 Math.random()生成指定范围内的随机数的公式推导

    关于 Math.random()生成指定范围内的随机数的公式推导 在 java 中,用于生成随机数的 Math 方法 random()只能生成 0-1 之间的随机数,而对于生成指定区间,例如 a-b ...

  4. javascript 生成指定范围内的随机数

    js 生成任意2个区间内的随机整数,js 生成两个数之间的随机数 function random(m,n) { return Math.floor(Math.random() * (n - m)) + ...

  5. shell生成指定范围内的随机数

    #!/bin/bash read -p "请输入起始数:" min read -p "请输入终止数:" max if [ $min -gt $max ] the ...

  6. SQL - 生成指定范围内的随机数

    今天按照公司需求,需要做一个sql作业来对数据库定时触发,其中有个难点,就是在sql中需要在1-n中随机出来一个结果. google了半天,找到一个比较好的方式. 写下这个sql: DECLARE @ ...

  7. 【转】 SQL - 生成指定范围内的随机数

    DECLARE @Result INT DECLARE @Upper INT DECLARE @Lower INT SET @Lower = 1 SET @Upper = 10 SELECT @Res ...

  8. js中Math.random()生成指定范围数值的随机数

    http://www.111cn.net/wy/js-ajax/57062.htm Math.random() 这个方法相信大家都知道,是用来生成随机数的.不过一般的参考手册时却没有说明如何用这个方法 ...

  9. C#生成指定范围内的不重复随机数

    C#生成指定范围内的不重复随机数 // Number随机数个数 // minNum随机数下限 // maxNum随机数上限 public int[] GetRandomArray(int Number ...

随机推荐

  1. php大力力 [017节]来来来,庆祝一下🎁大力力第一个数据库录入程序完成!

    庆祝一下

  2. PHP使用mysqli操作MySQL数据库

    PHP的 mysqli 扩展提供了其先行版本的所有功能,此外,由于 MySQL 已经是一个 具有完整特性的数据库服务器 , 这为PHP 又添加了一些新特性 . 而 mysqli 恰恰也支持了 这些新特 ...

  3. Visual Studio 2010 单元测试

    转载出处:http://blog.csdn.net/tjvictor/article/details/6175362

  4. java多线程向数据库中加载数据

    读取本地文件,每行为一条记录,文件大小550M,200万条数据.先将文件读取的内存中,再开启6个线程连接postgresql不同coordinator端口导入数据.代码如下: import java. ...

  5. 图像金字塔及其在 OpenCV 中的应用范例(下)

    前言 本文将主要讲解如何使用 OpenCV 实现图像分割,这也是图像金字塔在 OpenCV 中的一个重要应用. 关于图像分割 在计算机视觉领域,图像分割(Segmentation)指的是将数字图像细分 ...

  6. genome file format

    Some of the bedtools (e.g., genomeCoverageBed,complementBed, slopBed) need to know the size of the c ...

  7. Bash Shell字符串操作小结

    装载自:http://my.oschina.net/aiguozhe/blog/41557 1. 取长度 str="abcd" expr length $str # 4 echo ...

  8. 使用jetty-maven-plugin插件进行测试

    为了能够使用maven的jetty插件对项目进行测试,需要进行如下操作: (1)修改maven配置文件 为了能够在命令行中使用jetty命令,需要修改maven的配置文件settings.xml文件, ...

  9. sqlserver mdf向上兼容附加数据库(无法打开数据库 'xxxxx' 版本 611。请将该数据库升级为最新版本。)

    最近工作中有一个sqlserver2005版本的mdf文件,还没有log文件,现在需要 附加到sqlserver2012,经过网上一顿搜索,把完整的过程奉上,供大家参考 首先创建数据库 再设置数据库的 ...

  10. javascript 火狐event.keyCode不能使用event is not defined

    在项目中,登录时需要enter按钮提交页面所以需要监听键盘输出 但是在火狐中不支持 event.code 所以换了中写法 1:form中加入时间传入event <form id="fr ...