传送门
首先根据欧拉降幂的公式得到 n n ! % φ ( p ) + φ ( p ) ( m o d p ) n^{n!\% \varphi(p)+\varphi(p)}(mod~~p) nn!%φ(p)+φ(p)(mod p),那么代码整体分三种情况考虑:
注意当 p = 1 p=1 p=1时,如果 m = 2 64 − 1 m=2^{64}-1 m=264−1,再加上 0 0 0恰好为 2 64 2^{64} 264爆范围,所以特判
//
// Created by Happig on 2020/8/26
//
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x, y) make_pair(x,y)
#define mem(a, x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double dinf = 1e300;
const ll INF = 1e18;
const int Mod = 1e9 + 7;
const int maxn = 2e5 + 10;
ull euler_phi(ull n) {
int m = sqrt(n + 0.5);
ull ans = n;
for (int i = 2; i <= m; i++)
if (n % i == 0) {
ans = ans * (i - 1) / i;
while (n % i == 0) n /= i;
}
if (n > 1) ans = ans * (n - 1) / n;
return ans;
}
ull qkp(ull x, ull n, ull p) {
ull ans = 1;
x %= p;
while (n) {
if (n & 1) ans = ans * x % p;
x = x * x % p;
n >>= 1;
}
return ans;
}
int cnt[maxn];
int main() {
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t, kase = 0;
ull b, p, m;
cin >> t;
while (t--) {
cin >> b >> p >> m;
cout << "Case #" << ++kase << ": ";
if (p == 1) {
if (m == 18446744073709551615ull)
cout << "18446744073709551616\n";
else cout << m + 1 << "\n";
continue;
}
ull phi = euler_phi(p), cur = 1, ans = 0, l;
if (b == 0) ans++;
for (int i = 1; i <= m; i++) {
cur *= i, l = i;
if (cur >= phi) break;
if (qkp(i, cur, p) == b) ans++;
}
if (cur < phi) {
cout << ans << "\n";
continue;
}
cur %= phi;
if (qkp(l, cur + phi, p) == b) ans++;
for (l = l + 1; l <= m; l++) {
cur = (cur * l) % phi;
if (cur == 0) break;
if (qkp(l, cur + phi, p) == b) ans++;
}
if (l <= m) {
ll num = 0;
for (int i = 0; i < p; i++) {
if (qkp(i + l, phi, p) == b) cnt[i] = 1, num++;
else cnt[i] = 0;
}
ll k = (m - l + 1) / p;
ans += num * k;
ll res = (m - l + 1) % p;
for (int i = 0; i < res; i++) ans += cnt[i];
}
cout << ans << "\n";
}
return 0;
}