玲珑杯 Round #5 Problem E Tetration (枚举 + 欧拉公式)
题目链接 Tetration
题意 给定一个排列 现在可以任意调整这个排列的顺序
求$a_{1}^{a_{2}^{a_{3}^{...^{a_{n}}}}}$对$p$取模的最小值
直接枚举$a$的每一个排列,然后计算取最小值即可。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) #define MP make_pair #define fi first #define se second typedef long long LL; const int N = 10; int n; int T; int f[N]; LL a[N], c[N]; LL m; LL ans; map <LL, LL> mp; LL phi(LL n){ if (mp.count(n)) return mp[n]; LL ans = n, z = n; for (LL i = 2; i * i <= n; ++i){ if (n % i == 0){ ans -= ans / i; while (n % i == 0) n /= i; } } if (n > 1) ans -= ans / n; return mp[z] = ans; } LL Pow(LL a, LL b, LL mod){ LL ret = 1; LL fl = a >= mod; for (; b; b >>= 1){ if (b & 1){ ret *= a; if (ret >= mod) fl = 1, ret %= mod; } a *= a; if (a >= mod) a %= mod, fl = 1; } return ret + fl * mod; } LL solve(int l, int r, LL mod){ if (l == r) return c[l]; if (mod == 1) return 1; return Pow(c[l], solve(l + 1, r, phi(mod)), mod); } int main(){ scanf("%d", &T); while (T--){ scanf("%d%lld", &n, &m); ans = 1e18; rep(i, 1, n) scanf("%lld", a + i); rep(i, 1, n) f[i] = i; do{ rep(i, 1, n) c[i] = a[f[i]]; ans = min(ans, solve(1, n, m) % m); } while (next_permutation(f + 1, f + n + 1)); printf("%lld\n", ans); } return 0; }