传送门
题意:求 2(2(2...))modp 的值,多组询问。 p≤107 。
Solution:
根据扩展欧拉定理,我们知道:
当 b≥φ(p) 时, ab≡ab%φ(p)+φ(p)modp
此公式的具体证明可以百度扩展欧拉定理
我们假设 f(p)=2(2(2...))modp ,那么 f(1)=0
由公式可得:
f(p)=2(2(2...))modp
=2(2(2(2...))%φ(p)+φ(p))modp
=2f(φ(p))+φ(p)modp
由此我们就得到了 f(p) 的递推式
但是这样复杂度可能有问题?
我们来大力分析一波:
如果p为偶数,根据计算公式 φ(x)=x∏ni=1(pi−1pi) ,我们一定会乘上一个 12 ,所以说 φ(x)≤x2
如果p为奇数,那么他定会包含奇质因子,再结合公式,一定会乘一个偶数,所以说 φ(x) 一定会是偶数
由这些我们就可以知道,我们递归一次只需要 O(logn) 的复杂度,因此总复杂度 O(Tp√logp)
代码:
#include<cstdio>
#include<iostream>
using namespace std;
int t,n;
bool vis[10000010];
int F[10000010];
int fast_pow(int a,int x,int mod)
{
int ans=1;
for (;x;x>>=1,a=1ll*a*a%mod)
if (x&1) ans=1ll*ans*a%mod;
return ans;
}
int phi(int x)//根据公式进行计算
{
int ret=x;
for (int i=2;i*i<=n;i++)
{
if (x%i==0)
{
ret-=ret/i;
while (x%i==0)
x/=i;
}
}
if (x>1) ret-=ret/x;
return ret;
}
int f(int x)
{
if (vis[x]) return F[x];
int p=phi(x);
vis[x]=1;
return F[x]=fast_pow(2,f(p)+p,x);
}
int main()
{
scanf("%d",&t);
vis[1]=1;F[1]=0;
while (t--)
{
scanf("%d",&n);
printf("%d\n",f(n));
}
}