玲珑杯 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;
}

  

 

posted @ 2018-01-30 22:27  cxhscst2  阅读(246)  评论(0编辑  收藏  举报