就是需要用到一个欧拉定理
(a^b)%p=(a^(b%phi(p)))%p。
但是这个公式只在a与p互质的情况下才可以用。
所以需要用到一个适用范围更广的公式。
如果b>=phi(p) (a^b)%p=(a^(b%phi(p)+phi(p)))%p。
否则 (a^b)%p=(a^b)%p。
这样就可以降幂,然后用next_permutation函数枚举所有排列,计算出相应结果,并保存最小值即可。
这道题主要不是卡你枚举的时间复杂度,也不是卡你快速幂或者降幂的时间复杂度,而是卡你知不知道这个公式。因为如果你没有这个公式,你在求幂的过程中就不能取余,这样就会溢出,从而得不到答案。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll phi(ll n)
{
ll ret=n;
ll m=sqrt(n+0.5);
for(ll i=2;i<=m;i++)
{
if(n%i==0)
{
ret=ret/i*(i-1);
while(n%i==0) n/=i;
}
}
if(n>1)
ret=ret/n*(n-1);
return ret;
}
ll mp(ll x,ll n,ll m)
{
ll ret=1;
while(n)
{
if(n&1)
{
ret*=x;
if(ret>=m)
{
ret%=m;
ret+=m;
}
}
x*=x;
if(x>=m)
{
x%=m;
x+=m;
}
n>>=1;
}
return ret;
}
ll n,p;
ll a[10];
ll P[10];
ll cul()
{
ll zhi=1;
for(ll i=n-1;i>=0;i--)
zhi=mp(a[i],zhi,P[i]);
return zhi%P[0];
}
int main()
{
ll T;
for(scanf("%lld",&T);T;T--)
{
scanf("%lld %lld",&n,&p);
for(ll i=0;i<n;i++)
scanf("%lld",&a[i]);
sort(a,a+n);
P[0]=p;
for(ll i=1;i<n;i++)
P[i]=phi(P[i-1]);
ll ans=LONG_LONG_MAX;
do
{
ans=min(ans,cul());
}while(next_permutation(a,a+n));
printf("%lld\n",ans);
}
return 0;
}