UVA 10006(卡迈克尔数+素数打表)

来源:互联网 发布:java返回值类型是什么 编辑:程序博客网 时间:2024/05/01 08:07

uva10006 Carmichael Numbers(卡迈克尔数+素数打表)

发表于2017/2/20 21:43:25  16人阅读

分类: 其他oj 数论-组合数学


https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=12&page=show_problem&problem=947

题意:判断一个数是否是卡迈克尔数。



刚开始看到x^n≡x(mod n)老实说把我吓了一跳,一个数余n怎么会搞出一个这么大的数。想了半天一度怀疑人生,去翻题解,结果主流都是相当于求解x≡x^n(mod n),就以为是不是书中印错了。直到后来看到了卡迈克尔数的定义:


我擦嘞原来人家真的是这么定义的,再往下翻好像和费马小定理类似。。什么??费马小定理??好像前几天看过没看懂。。

是的和费马小定理一毛一样。。

好吧,看来书是对的,可是还是不能说明这个式子的不合理性呀。

直到看见同余式的定义:


原来b^(n-1)-1能被n整除就行。。同余式的概念没理解。。这下真的怀疑人生了。。

问题又来了,怎么算出整除结果呢?没错这就是卡迈克尔数的难度,是否是卡迈克尔数的公式要自己推啊,现在还没有最标准的解,要不怎么会有余建春这种风靡一时的事迹。。


我们再看一眼题:


用自己吃奶的英语翻译,人家先是给了一个式子,然后说如果这个数通过了费马测试(后来验证这不是费马测试的式子,只是打错了而已)就是可靠性高的。但是很不幸!有一些不是素数的仍然通过了费马测试,这些书就叫卡迈克尔数。这个问题就是让你写个程序判断是否是卡迈克尔数。

至少可以肯定不是按照给出的这个式子解了,和这个式子无关。


扫了一眼网上的题解,感觉也就这个比较正确:大牛orz

主要给出的是一个判别法,很有价值:


不过这大牛题解第一句话就没看懂,什么“根据考塞特判别法,我们只需要求≤maxn/3的素数”,为毛要除啊声泪俱下。。

索性自己按照着定理来了一遍,虽然时间多一点,不过感觉更容易懂。

顺便体验了一把uva的龟速:(真正体验到了时差,我是晚上做的)


同时也向余建春表示敬意,居然真的有人闲的没事研究这种问题,我这渣渣望其项背啊。。

哎,又一个题做了一天,这种题下次遇到放到以后做吧,密码学也许研究生才学,不过现在只是想争取学的机会啊,别越级打怪了。。


。。。


最后还有一个问题,那些用快速幂过的连公式都没用对,到底是怎么过的??



#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;typedef long long ll;const int N = 66000;int prime[N], num[N], cnt = 0;void prime_table(){    memset(prime, 1, sizeof(prime));    for(int i = 2; i <= N; i++)    {        if(prime[i])        {            for(int j = i+i; j <= N; j+=i)                prime[j] = 0;        }    }}void choose_prime(){    for(int i = 2; i <= N; i++)        if(prime[i]) num[cnt++] = i;}int main(){    prime_table();    choose_prime();  //  freopen("in.txt", "r", stdin);    int n, flag;    while(~scanf("%d", &n))    {        flag = 1;        if(n == 0) break;        if((!prime[n]) && (n%2==1))        {            for(int i = 0; num[i] < n; i++)            {                if(n%num[i] == 0)                {                    if(n%(num[i]*num[i])==0 || (n-1)%(num[i]-1))                    {                        flag = 0;                    }                }            }        }        else        {            flag = 0;        }        if(flag) printf("The number %d is a Carmichael number.\n", n);        else printf("%d is normal.\n", n);    }    return 0;}
0 0
原创粉丝点击