uva 10006 Carmichael Numbers 快速幂

缘起

日常水题 uva 10006 Carmichael Numbers

分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
我们把都对任意的1<x<n都有 x^n和x关于模掉n同余的合数x成为卡米切尔数. 对于给定的正整数n(2<n<65000) 判定
它是不是卡米切尔数.

【输入】
每行一个n, 直至0

【输出】
看样例输出

【样例输入】
1729
17
561
1109
431
0

【样例输出】
The number 1729 is a Carmichael number.
17 is normal.
The number 561 is a Carmichael number.
1109 is normal.
431 is normal.

【限制】
Time limit 3000 ms

鉴于n只到了65000,所以sqrt(n)足以. 而不需要 Miller-rabin测试. 然后快速幂即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//#include "stdafx.h"

#include <stdio.h>
#include <math.h>
//#define LOCAL

typedef long long LL; // 65000*65000 将达到42亿+
LL n;

bool isprime()
{
LL x = (LL)(sqrt(n*1.0)+0.5); // +0.5防止精度丢失
for (LL i = 2; i<=x; i++)
{
if (!(n%i))
{
return false;
}
}
return true;
}

bool sz()
{
for (LL x = 2,m,ans,t,y; x<n ;x++) // 考察 x^n模掉n的余数
{
m = n;
ans = 1;
y = x;
while(m) // 快速幂计算 x^n 模掉n的余数
{
if (m&1)
{
ans = (ans%n)*(y%n);
}
if (m>1)
{
y = (y%n)*(y%n);
}
m>>=1;
}
if (ans%n!=x)
{
return false;
}
}
return true;
}

int main()
{
#ifdef LOCAL
freopen("d:\\data.in", "r", stdin);
//freopen("d:\\my.out", "w", stdout);
#endif
while(scanf("%lld", &n), n)
{
if (isprime())
{
printf("%lld is normal.\n", n);
}
else
{
if (sz())
{
printf("The number %lld is a Carmichael number.\n",n);
}
else
{
printf("%lld is normal.\n", n);
}
}
}
return 0;
}

ac情况

Status Accepted
Time 160ms
Length 943
Lang C++11 5.3.0
Submitted 2019-08-23 10:35:21
Shared
RemoteRunId 23808999