1
+ #include < bits/stdc++.h>
2
+
3
+ #include < bits/stdc++.h>
4
+
5
+ using namespace std ;
6
+
7
+ using u128 = __uint128_t ;
8
+ using s128 = __int128_t ;
9
+ using u64 = uint64_t ;
10
+
11
+ inline u128 mul (u128 x, u128 y, u128 c)
12
+ {
13
+ u128 ans = 0 ;
14
+ static const u64 shift = 25 ;
15
+ while (y) {
16
+ ans += x*(y&((1 <<shift)-1 ));
17
+ x = (x<<shift)%c;
18
+ y >>= shift;
19
+ }
20
+ return ans % c;
21
+ }
22
+
23
+ u128 HI (u128 x) { return x>>64 ; };
24
+ u128 LO (u128 x) { return u64 (x); };
25
+
26
+ namespace Prime {
27
+
28
+ int const num_tries = 20 ;
29
+
30
+ u128 power (u128 a, u128 b, u128 c) {
31
+ u128 ans = 1 ;
32
+ while (b) {
33
+
34
+ if (b&1 ) ans = mul (ans, a, c);
35
+ a = mul (a, a, c);
36
+ b >>= 1 ;
37
+ }
38
+ return ans;
39
+ }
40
+
41
+ bool witness (u128 base, u128 s, u128 d, u128 n) {
42
+ u128 x = power (base, d, n);
43
+ u128 y;
44
+ while (s--) {
45
+
46
+ y = mul (x, x, n);
47
+ if (y == 1 and x != 1 and x != n-1 ) return false ;
48
+ x = y;
49
+ }
50
+ if (x != 1 ) return false ;
51
+ return true ;
52
+ }
53
+
54
+ mt19937_64 rd;
55
+
56
+ bool is_prime (u128 x) {
57
+ if (x == 2 or x == 3 or x == 1 ) return true ;
58
+ if (x % 2 == 0 or x % 3 == 0 ) return false ;
59
+
60
+ u128 s = 1 , d = x>>1 ;
61
+ while (!(d&1 )) s++, d>>= 1 ;
62
+
63
+ uniform_int_distribution<u64 > rng (2 , HI (x)? u64 (-1ull ): (u64 (x)-1 ));
64
+
65
+ for (int i = 0 ; i < num_tries; i++) {
66
+ u64 p = rng (rd);
67
+ if (!witness (p, s, d, x)) return false ;
68
+ }
69
+ return true ;
70
+ }
71
+ } // end namespace Prime
72
+
73
+ namespace Factor {
74
+
75
+ int const num_tries = 10 ;
76
+
77
+ u128 n, niv_n;
78
+ void setn (u128 n_) {
79
+ // calculates multiplicative inverse of n mod 2^128
80
+ // to use in modular reduction (how?)
81
+ n = n_;
82
+ niv_n = 1 ;
83
+ u128 x = n;
84
+ for (int i = 1 ; i <= 126 ; i++)
85
+ {
86
+ niv_n*=x;
87
+ x*=x;
88
+ }
89
+ }
90
+
91
+ struct u256 {
92
+ u128 hi, lo;
93
+
94
+ static u256 mul128 (u128 x,u128 y) {
95
+ u128 t1 = LO (x)*LO (y);
96
+ u128 t2 = HI (x)*LO (y) + HI (y)*LO (x) + HI (t1);
97
+ return { HI (x)*HI (y) + HI (t2) , (t2<<64 ) + LO (t1) };
98
+ }
99
+ };
100
+
101
+ u128 mmul (u128 x,u128 y) {
102
+ u256 m = u256::mul128 (x,y);
103
+ // some kind of montgomery reduction?
104
+ u128 ans = m.hi - u256::mul128 (m.lo *niv_n, n).hi ;
105
+ if (s128 (ans) < 0 ) ans += n;
106
+ return ans;
107
+ }
108
+
109
+ inline u128 f (u128 x, u128 inc) {
110
+ return mmul (x, x) + inc;
111
+ }
112
+
113
+ inline u128 gcd (u128 a, u128 b) {
114
+ auto ctz = [] (u128 x) {
115
+ if (!HI (x)) return __builtin_ctzll (x);
116
+ return 64 + __builtin_ctzll (x>>64 );
117
+ };
118
+
119
+ int shift = ctz (a|b);
120
+ b >>= ctz (b);
121
+ while (a) {
122
+ a >>= ctz (a);
123
+ if (a < b) swap (a, b);
124
+ a -= b;
125
+ }
126
+ return b << shift;
127
+ }
128
+
129
+ inline u128 rho (u128 seed, u128 n, u64 inc) {
130
+ static const int step=1 <<9 ;
131
+
132
+ setn (n);
133
+
134
+ auto sub = [&] (u128 x, u128 y) { return x>y ? x-y:y-x; };
135
+
136
+ u128 y = f (seed, inc);
137
+
138
+ for (int l=1 ;; l<<=1 )
139
+ {
140
+ u128 x = y;
141
+ for (int i = 1 ; i <= l; i++) y = f (y, inc);
142
+ for (int k = 0 ; k < l; k += step)
143
+ {
144
+ int d = min (step, l-k);
145
+ u128 g = seed, y0 = y;
146
+
147
+ for (int i = 1 ; i <= d; i++) {
148
+ y = f (y, inc);
149
+ g = mmul (g, sub (x,y));
150
+ }
151
+
152
+ g = gcd (g,n);
153
+
154
+ if (g==1 ) continue ;
155
+ if (g!=n) return g;
156
+
157
+ u128 y = y0;
158
+
159
+ while (gcd (sub (x,y), n) == 1 ) y = f (y, inc);
160
+
161
+ return gcd (sub (x,y), n) % n;
162
+ }
163
+ }
164
+ return 0 ;
165
+ }
166
+
167
+ mt19937_64 rd;
168
+
169
+ u128 rho (u128 x) {
170
+ if (x <= 3 ) return 0 ;
171
+ if (x%2 == 0 ) return 2 ;
172
+ if (x%3 == 0 ) return 3 ;
173
+
174
+ uniform_int_distribution<u64 > rng (2 , HI (x)? u64 (-1ull ): (u64 (x)-1 ));
175
+
176
+ for (u128 i = 2 ; i < num_tries; i++) {
177
+ u128 ans = rho (rng (rd), x, i);
178
+ if (ans != 0 and ans != x) return ans;
179
+ }
180
+ return 0 ;
181
+ }
182
+
183
+ void factor (u128 x, vector<u128 >& primes) {
184
+
185
+ if (Prime::is_prime (x)) primes.push_back (x);
186
+ else {
187
+ u128 fac = rho (x);
188
+ factor (fac, primes);
189
+ factor (x/fac, primes);
190
+ }
191
+ }
192
+
193
+ vector<u128 > factor (u128 x) {
194
+ vector<u128 > v;
195
+ factor (x, v);
196
+ sort (v.begin (), v.end ());
197
+ return v;
198
+ }
199
+
200
+ vector<pair<u128 ,u128 >> factor_pairs (u128 x) {
201
+ auto v = factor (x);
202
+ vector<pair<u128 , u128 >> res;
203
+
204
+ for (int i = 0 ; i < (int )v.size (); i++) {
205
+ if (i == 0 or res.back ().first != v[i])
206
+ res.emplace_back (v[i], 1 );
207
+ else
208
+ res.back ().second ++;
209
+ }
210
+ return res;
211
+ }
212
+ } // end namespace Factor
213
+
214
+ template <typename T>
215
+ void read (T &x)
216
+ {
217
+ #define gc (c=getchar())
218
+
219
+ char c;
220
+ while (gc < ' 0' );
221
+ x = c - ' 0' ;
222
+ while (gc >= ' 0' ) x = x*10 + c - ' 0' ;
223
+
224
+ #undef gc
225
+ }
226
+
227
+ template <typename T>
228
+ void write (T x, char c = ' \n ' )
229
+ {
230
+ static char st[40 ];
231
+ int top=0 ;
232
+ do {st[++top] = ' 0' + x%10 ;} while (x /=10 );
233
+ do {putchar (st[top]);} while (--top);
234
+ if (c != 0 ) putchar (c);
235
+ }
236
+
237
+ template <typename T>
238
+ T gcd (T a, T b) {
239
+ if (b == 0 ) return a;
240
+ return gcd (b, a%b);
241
+ }
242
+
243
+ template <typename T>
244
+ T lcm (T a, T b) {
245
+ return a/gcd (a, b)*b;
246
+ }
247
+
248
+ template <typename T>
249
+ T power (T a, T b) {
250
+ T ans = 1 ;
251
+ while (b) {
252
+ if (b&1 ) ans *= a;
253
+ a *= a;
254
+ b >>= 1 ;
255
+ }
256
+ return ans;
257
+ }
258
+
259
+ template <typename T>
260
+ T carmichael (pair<T, T> const & x) {
261
+ T ans = power (x.first , x.second -1 ) * (x.first -1 );
262
+ return ans;
263
+ }
264
+ template <typename T>
265
+ T carmichael (T x) {
266
+ auto factors = Factor::factor_pairs (x);
267
+ T ans = 1 ;
268
+
269
+ for (auto const & i : factors) {
270
+ ans = lcm (ans, carmichael (i));
271
+ }
272
+
273
+ return ans;
274
+ }
275
+
276
+ int main () {
277
+ u128 x;
278
+ read (x);
279
+
280
+ write (carmichael (x));
281
+ }
0 commit comments