题目地址https://vjudge.net/contest/236648#problem/G。
这题的关键就是要用到欧拉定理降幂,欧拉定理就是 a^(φ(m))同余1(mod m) (a与m互质),
其中φ(m)为欧拉函数,具体运算方法为 设n=(p1^a1)*(p2^a2)*……*(pk^ak) (为N的分解式) 那么φ(n)=n*(1-1/p1)*(1-1/p2)*……*(1-1/pk)。
代码如下:
long long Euler(long long n)
{
long long res=n,ans=n;
for (int i=2;i*i<=ans;i++)//类似于筛法
{
if (ans%i==0)
{
res=res/i*(i-1);//先除后乘防止溢出
while (ans%i==0)
{
ans/=i;
}
}
}
if (ans>1) res=res/ans*(ans-1);//ans为质数的情况
return res;
}
但由于欧拉定理要求a,m互质,而题目中的情况可能是不互质的,这时要使用扩展的欧拉定理,
,其中为任意整数,为正整数,并且(注意这里a和m不一定互素)
证明见https://zhuanlan.zhihu.com/p/24902174 。
这时只要保证就可以了,又因为φ(m)<m<=1E9,而exponial(5) ≈ 6.206 ⋅ 10E183230远远大于10E9,所以当n>5时就可以安心用上述公式了。
通过代码如下:
#include<cstdio>
long long Euler(long long n)
{
long long res=n,ans=n;
for (int i=2;i*i<=ans;i++)
{
if (ans%i==0)
{
res=res/i*(i-1);
while (ans%i==0)
{
ans/=i;
}
}
}
if (ans>1) res=res/ans*(ans-1);
return res;
}
long long pow(long long n,long long p,long long m)
{
long long res=1,x=n;
while (p)
{
if (p&1) res=(res*x)%m;
x=(x*x)%m;
p>>=1;
}
return res;
}
long long result(long long n,long long m)
{
if (m==1) return 0;//为什么不加就会超时 (100000 1)
if (n==1) return 1%m;
if (n==2) return 2%m;
if (n==3) return 9%m;
if (n==4) return 262144%m;
long long tmp=Euler(m);
return pow(n,result(n-1,tmp)+tmp,m);
}
int main()
{
int n,m;
while (scanf("%d %d",&n,&m)==2 &&n &&m)
{
printf("%d\n",result(n,m));
}
return 0;
}
仍然存在的两个问题:
1、实际上在通过代码中,n=5的情况没有考虑,此时x=exponial(4)=262144,而如果m取100000007,
φ(m)=100000006>x,不满足条件。
2、在result 函数中如果不加 if (m==1) return 0 会超时,但不明白为什么会这样。
希望有大佬们能帮忙解决。