UVA10006 - Carmichael Numbers
当今计算机科学的一个重要的领域就是密码学。有些人甚至认为密码学是计算机科学中唯一重要的领域,没有密码学生命都没有意义。
阿尔瓦罗就是这样的一个人,它正在设计一个为西班牙杂烩菜饭加密的步骤。他在加密算法中应用了一些非常大的素数。然而确认一个非常大的数是不是素数并不是那么简单。一个费时的方法是用比这个数的平方根小的所有素数去除它,对于大整数来说,这样一定会毁掉这个杂烩菜饭的。
然而,一些很有信心耗时少的随机测试存在,其中一个就是费马测试。
在2和n-1之间随机选取一个数(n是我们要测试的数)。如果a n mod n = a 成立,n就可能是一个素数。
如果一个数通过费马测试很多次那么它就很可能是一个素数。
不幸的是,一些数不是素数但是它们依然能通过每一个比它小的数的费马测试。这些数被称作卡迈克尔数
这道题要求你写一个程序去测试给定的数是不是一个卡迈克尔数。
完成了这个任务的队伍有希望接受来自阿尔瓦罗的西班牙杂烩菜饭23333
Input
多组输入,第一行给一个n (2 < n < 65000) 。n = 0 表示输入结束并不需要处理
Output
对每组输入,输出它是不是卡迈克尔数,参考样例。
Sample Input
1729
17
561
1109
431
0
Sample Output
The number 1729 is a Carmichael number.
17 is normal.
The number 561 is a Carmichael number.
1109 is normal.
431 is normal.
思路:此题比较麻烦,需要提前打表,狂wa,2333
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
typedef long long LL;
int prime[65000];
LL powmod( int a, int n, int m )
{
if ( n == 1 ) return a%m;
LL x = powmod( a, n/2, m );
x = (x*x)%m;
if ( n%2 ) x = (x*a)%m;
return x;
}
int tests( int n )
{
for ( int i = 2 ; i < n ; ++ i )
if ( powmod( i, n, n ) != i )
return 0;
return 1;
}
int main()
{
//打表计算素数
for ( int i = 0 ; i < 65000 ; ++ i )
prime[i] = 1;
for ( int i = 2 ; i < 65000 ; ++ i )
if ( prime[i] )
for ( int j = 2*i ; j < 65000 ; j += i )
prime[j] = 0;
int n;
while ( cin >> n && n )
if ( !prime[n] && tests( n ) )
cout << "The number " << n << " is a Carmichael number.\n";
else cout << n << " is normal.\n";
return 0;
}