UVA10837
在这里插入图片描述
由唯一分解定理:

由欧拉函数定义:

因此,对于给定的$\phi(n)$,我们可以将所有符合条件$m\mod (p_i-1)==0$的素数筛选出来,然后再枚举选取多个$p_i$即可。
但由于素数表只打到10000以内的素数,即$\sqrt {phi_n}$。不过由于大于$\sqrt {phi_n}$的素数至多有一个,所以在特判即可。
因为最后一个素数的范围为$[2,phi_n]$,因此只要这个数与$[2,\sqrt{phi_n}]$内的所有数互质,那么它就是素数。
以下函数为判断最后一个选取的素数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
inline bool Judgt(const int& Remainder) {
//遍历素数表,判断最后剩下的是否为素数
for (int i = 0; i < PrimeTable.size(); ++i) {
const int& prime = PrimeTable[i];
if (Remainder % prime == 0) {
return false;
}
if (prime * prime > Remainder) {
break;
}
}

//返回是否未选过
return Used.find(Remainder) == Used.end();
}

完整代码:

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <queue>
#include <string>
#include <unordered_set>
using namespace std;

int m;

bool IsNotPrime[10001];

vector<int> PrimeTable;

vector<int> Candidates;

unordered_set<int> Used;


void InitPrimeTable() {
for (int i = 2; i <= 10000; ++i) {
if (IsNotPrime[i] == false) {
PrimeTable.push_back(i);
for (int j = i * i; j <= 10000; j += i) {
IsNotPrime[j] = true;
}
}
}
}

void InitCandidates() {
for (int i = 0; i < PrimeTable.size(); ++i) {
const int& prime = PrimeTable[i];
if (m % (prime - 1) == 0) {
Candidates.push_back(prime);
}
if ((prime - 1) * (prime - 1) > m) {
break;
}
}
}

int Ans;

inline bool Judgt(const int& Remainder) {
for (int i = 0; i < PrimeTable.size(); ++i) {
const int& prime = PrimeTable[i];
if (Remainder % prime == 0) {
return false;
}
if (prime * prime > Remainder) {
break;
}
}

return Used.find(Remainder) == Used.end();
}

void DFS(int Index = 0, int Remainder = m, int n = 1) {
if (Index == Candidates.size()) {
if (Remainder == 1) {
Ans = min(Ans, n);
}
else if (Judgt(Remainder + 1)) {
n *= (Remainder + 1);
Ans = min(Ans, n);
}
return;
}

DFS(Index + 1, Remainder, n);

const int& CurPrime = Candidates[Index];

if (Remainder % (CurPrime - 1)) {
return;
}

Used.insert(CurPrime);

Remainder /= (CurPrime - 1);
n *= CurPrime;

DFS(Index + 1, Remainder, n);

while (Remainder % CurPrime == 0) {
Remainder /= CurPrime;
n *= CurPrime;
DFS(Index + 1, Remainder, n);
}

Used.erase(CurPrime);

}

void InitData() {
Ans = 200000000;
Candidates.clear();
Used.clear();
}

int main() {

InitPrimeTable();

int Case = 0;

while (~scanf("%d", &m) && m) {
InitData();
InitCandidates();
DFS();
printf("Case %d: %d %d\n", ++Case, m, Ans);
}

return 0;

}