您的位置:首页 > 其它

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

2017-02-20 21:43 483 查看
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
, num
, 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%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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  uva 卡迈克尔数