BZOJ3844 上帝与集合的正确用法

2018 年 03 月 14 日发布.

Description

给定$p$,求$2^{2^{2^{2^{\cdots}}}}\bmod p$。$p\leqslant 10^7$。

Solution

令$f(p)=2^{2^{2^{2^{\cdots}}}}\bmod p$。由于$b>\phi(p)$时$a^b\equiv a^{(b\,mod\,\phi(p))+\phi(p)}\pmod{p}$。所以$f(p)=2^{f(\phi(p))+\phi(p)}\pmod{p}$。

由于易证$\phi(\phi(p))\leqslant\frac p2$,所以时间为$O(\log p)$。

Code

#include <cstdio>
typedef long long LL;
const int N = 10000050;
int phi[N], pr[N / 10], cnt;
int pow_mod(int a, int b, int p) {
  int ans = 1;
  for (; b; b >>= 1, a = (LL)a * a % p)
    if (b & 1) ans = (LL)ans * a % p;
  return ans;
}
int calc(int p) {
  // 2 ^ (2 ^ (...)) % p
  if (p == 1) return 0;
  return pow_mod(2, calc(phi[p]) + phi[p], p);
}
int main() {
  for (int i = 1; i < N; ++i) phi[i] = i;
  for (int i = 2; i < N; ++i) {
    if (phi[i] == i)
      --phi[pr[cnt++] = i];
    for (int j = 0; j < cnt && (LL)pr[j] * i < N; ++j) {
      if (i % pr[j])
        phi[i * pr[j]] = phi[i] * phi[pr[j]];
      else {
        phi[i * pr[j]] = phi[i] * pr[j];
        break;
      }
    }
  }
  int T, p;
  scanf("%d", &T);
  while (T--) {
    scanf("%d", &p);
    printf("%d\n", calc(p));
  }
}