1.HDU4335
我们先将转化为.
然后分情况讨论:
1.n! <= phi(p)时,我们直接枚举有多少n满足条件即可
2.n! > phi(p)时,注意到,当出现一个 n 使得n! % phi(p) == 0,那么对于i > n,一定都有 i! % phi(p) == 0,因为 i! 包括 n!.所以,当n! % phi(p) != 0时,我们依旧枚举有多少个 n 满足条件.
3.当 n! % phi(p) == 0时,式子变成,这部分其实是存在循环节的,并且长度为p,具体证明可以查阅网上资料,这里不再赘述.我们求出每个循环节有多少个n是满足条件的即可.
最后补充一点,这道题的题给数据很大,尤其是对于ull_max 的情况,我们要进行特判,其他的数据也要开 ull 而不只是 ll
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <map>
#include <unordered_map>
#include <vector>
#include <stack>
#include <time.h>
#include <set>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define PII pair<int, int>
#define PDI pair<double, int>
#define int long long
#define ll long long
#define ull unsigned long long
#define eps 1e-6
#define MOD 1000000007
#define debug(a) cout << #a << "=" << a << endl;
#define all(x) (x).begin(), (x).end()
#define mem(x, y) memset((x), (y), sizeof(x))
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
ull b, p, m;
ull get_phi(int n) {
ull ans = n;
for (int i = 2; i <= n / i; ++i) {
if (n % i == 0) {
ans = ans / i * (i - 1);
while (n % i == 0)
n /= i;
}
}
if (n > 1)
ans = ans / n * (n - 1);
return ans;
}
ull qpow(ull a, ull k, ull p) {
ull res = 1;
while (k) {
if (k & 1)
res = res * a % p;
k >>= 1;
a = a * a % p;
}
return res;
}
signed main() {
#ifdef LOCAL
freopen("input.in", "r", stdin);
freopen("output.out", "w", stdout);
#endif
IOS;
int T, Case = 0;
cin >> T;
while (T--) {
cout << "Case #" << ++Case << ": ";
cin >> b >> p >> m;
if (p == 1) {
if (m == 18446744073709551615ull)
cout << "18446744073709551616\n";
else
cout << m + 1 << "\n";
continue;
}
//1.i! <= phi(p)
int i = 0, phi = get_phi(p);
ull fac = 1, ans = 0;
for (; i <= m && fac <= phi; ++i) {
if (qpow(i, fac, p) == b)
++ans;
fac *= i + 1;
}
//2.i! > phi(p) 且 i! % phi(p) != 0
fac %= phi;
for (; i <= m && fac; ++i) {
if (qpow(i, fac + phi, p) == b)
++ans;
fac = (fac * (i + 1)) % phi;
}
//3.i! % phi(p) = 0
if (i <= m) {
ull cnt = 0;//表示一个循环节中有多少个b
vector<int> ring(p);
for (int j = 0; j < p; ++j) {
ring[j] = qpow(i + j, phi, p);
if (ring[j] == b)
++cnt;
}
ans += (ull)(m - i + 1) / p * cnt;
ull remain = (m - i + 1) % p;
for (int j = 0; j < remain; ++j)
if (ring[j] == b)
++ans;
}
cout << ans << "\n";
}
}
2.hdu2837
这道题我们直接使用递归并搭配欧拉降幂即可,比较奇怪的是这道题的边界判断(题主也不知道为什么会这样).
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <map>
#include <unordered_map>
#include <vector>
#include <stack>
#include <time.h>
#include <set>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define PII pair<int, int>
#define PDI pair<double, int>
#define int long long
#define ll long long
#define ull unsigned long long
#define eps 1e-6
#define MOD 1000000007
#define debug(a) cout << #a << "=" << a << endl;
#define all(x) (x).begin(), (x).end()
#define mem(x, y) memset((x), (y), sizeof(x))
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
int n, m;
int qpow(int a, int k, int p) {
if (a == 0)
return k == 0;
int res = 1;
while (k) {
if (k & 1)
res = res * a % p;
k >>= 1;
a = a * a % p;
}
return res == 0 ? p : res;
}
int phi(int x) {
int ans = x;
for (int i = 2; i <= x / i; ++i)
if (x % i == 0) {
ans = ans / i * (i - 1);
while (x % i == 0)
x /= i;
}
if (x > 1)
ans = ans / x * (x - 1);
return ans;
}
int dfs(int n, int m) {
if (n == 0)
return 1;
if (n < 10)
return n;
return qpow(n % 10, dfs(n / 10, phi(m)), m);
}
signed main() {
#ifdef LOCAL
freopen("input.in", "r", stdin);
freopen("output.out", "w", stdout);
#endif
IOS;
int T;
cin >> T;
while (T--) {
cin >> n >> m;
cout << dfs(n, m) << "\n";
}
}
3.Luogu P4139
相比上面一题,这题可以直接套用欧拉降幂.
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <map>
#include <vector>
#include <unordered_map>
#include <stack>
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define PII pair<int, int>
#define PDI pair<double, int>
#define int long long
#define ll long long
#define ull unsigned long long
#define debug(a) cout << #a << "=" << a << endl;
#define all(x) (x).begin(), (x).end()
#define sd(x) scanf("%d", &(x))
#define sddd(x, y, z) scanf("%lld%lld%lld", &(x), &(y), &(z))
using namespace std;
const int N = 1e7 + 10;
int phi[N], primes[N], tot;
bool vis[N];
int qmi(int a, int k, int p) {
int res = 1;
while (k) {
if (k & 1)
res = res * a % p;
k >>= 1;
a = a * a % p;
}
return res;
}
void euler() {
phi[1] = 1;
for (int i = 2; i <= 10000000; ++i) {
if (vis[i] == 0) {
primes[++tot] = i;
phi[i] = i - 1;
}
for (int j = 1; j <= tot && i * primes[j] <= 10000000; ++j) {
vis[i * primes[j]] = 1;
if (i % primes[j] == 0) {
phi[i * primes[j]] = phi[i] * primes[j];
break;
}else
phi[i * primes[j]] = phi[i] * (primes[j] - 1);
}
}
}
int dfs(int u, int p) {
if (p == 1)
return 0;
return qmi(u, dfs(u, phi[p]) + phi[p], p);
}
void solve() {
int p;
cin >> p;
cout << dfs(2, p) << "\n";
}
signed main() {
#ifdef LOCAL
freopen("input.in", "r", stdin);
freopen("output.out", "w", stdout);
#endif
IOS;
euler();
int T;
cin >> T;
while (T--)
solve();
}