hdu 1014 Uniform Generator 数论

摘取于http://blog.csdn.net/kenden23/article/details/37519883;

找到规律之后本题就是水题了,不过找规律也不太容易的,证明这个规律成立更加不容易。

本题就是求step和mod如果GCD(最大公约数位1)那么就是Good Choice,否则为Bad Choice

为什么这个结论成立呢?

因为当GCD(step, mod) == 1的时候,那么第一次得到序列:x0, x0 + step, x0 + step…… 那么mod之后,必然下一次重复出现比x0大的数必然是x0+1,为什么呢?

因为(x0 + n*step) % mod; 且不需要考虑x0 % mod的值为多少,因为我们想知道第一次比x0大的数是多少,那么就看n*step%mod会是多少了,因为GCD(step, mod) == 1,那么n*step%mod必然是等于1,故此第一次重复出现比x0大的数必然是x0+1,那么第二次出现比x0大的数必然是x0+2,以此类推,就可得到必然会出现所有0到mod-1的数,然后才会重复出现x0.

当GCD(step, mod) != 1的时候,可以推出肯定跨过某些数了,这里不推了。

然后可以扩展这个结论,比如如果使用函数 x(n) = (x(n-1) * a + b)%mod;增加了乘法因子a,和步长b了;

那么如果是Good Choice,就必然需要GCD(a, mod) == 1,而且GCD(b, mod) == 1;

(另外的证明)

对于mod n域中的任意数a,若有gcd(m,n)=1,则m为该域的生成元,使得a+km可以为域中任意数.

证明十分简单,若gcd(m,n)=1,则lcm(m,n)=m*n,则对于a的mod n运算,需要n次的计算才能回到a,期间必遍历该域中所有数!

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define ll __int64
#define mod 1000000007
int scan()
{
    int res = 0 , ch ;
    while( !( ( ch = getchar() ) >= '0' && ch <= '9' ) )
    {
        if( ch == EOF )  return 1 << 30 ;
    }
    res = ch - '0' ;
    while( ( ch = getchar() ) >= '0' && ch <= '9' )
        res = res * 10 + ( ch - '0' ) ;
    return res ;
}
int gcd(int x,int y)
{
    return x%y?gcd(y,x%y):y;
}
int main()
{
    int x,y,z,i,t;
    while(~scanf("%d%d",&x,&y))
    {
        printf("%10d%10d",x,y);
        if(gcd(x,y)==1)
        printf("    Good Choice\n");//4个空格,pe多次
        else
        printf("    Bad Choice\n");
        printf("\n");
    }
    return 0;
}

  

posted @ 2016-03-28 19:46  jhz033  阅读(157)  评论(0编辑  收藏  举报