理论部分
欧拉定理:若 $a,n$ 为正整数,且 $a,n$ 互质,则 $a^{\varphi (n)} \equiv 1(mod \ n)$.
降幂公式:
$$a^b=
\begin{cases}
a^{b \% \varphi(p)} & gcd(a,p)=1 \\
a^b & gcd(a,p)\neq 1,b < \varphi (p) \\
a^{b\% \varphi (p) + \varphi (p)} & gcd(a,p)\neq 1,b \geq \varphi (p)
\end{cases}$$
题目
求 $2^{2^{2...}} \ mod \ p$ 的值,$T$组询问。$T \leq 1000, p \leq {10}^7$
分析:
首先,必须明确模意义下的无穷与真正的无穷是有区别的,(不然无穷的怎么求值
由降幂公式,当 $x \geq \varphi (p)$ 时(这道题中 $x$ 一直为2的无穷次方,肯定大于 $\varphi(p)$),
$$a^x \equiv a^{x \% \phi (p) + \varphi (p)}(mod \ p)$$
所以,令 $f(p) = 2^{2^{2...}}(mod \ p)$,$f(1)=0$,
$$\\f(p)=2^{(2^{2^{...}} mod \; \phi(p)) + \phi(p)}mod \; p \\=2^{f(\phi(p)) + \phi(p)} mod \ p$$
因此可以递归求解。
时间复杂度是多少呢?
求 $\phi(p)$ 是 $\sqrt p$,进行 $\varphi (\varphi (...\varphi (p))) = O(logp)$ 次,直至为1,
所以总的复杂度为 $O(\sqrt p log p)$
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int p;
ll qpow(ll a, ll b, ll p)
{
ll ret = 1;
while(b)
{
if(b&1) ret = ret*a%p;
a = a*a%p;
b >>= 1;
}
return ret;
}
int euler_phi(int n)
{
int m = (int)sqrt(n + 0.5);
int ans = n;
for (int i = 2; i <= m; i++)
{
if (n % i == 0)
{
ans = ans / i * (i - 1);
while (n % i == 0) n /= i; //除尽
}
}
if (n > 1) ans = ans / n * (n - 1); //剩下的不为1,也是素数
return ans;
}
int f(int p)
{
if(p == 1) return 0;
int phip = euler_phi(p);
return qpow(2, f(phip)+phip, p);
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d", &p);
printf("%d\n", f(p));
}
return 0;
}
参考链接:
1. https://blog.csdn.net/skywalkert/article/details/43955611
2. https://blog.csdn.net/qq_37632935/article/details/81264965
来源:oschina
链接:https://my.oschina.net/u/4336234/blog/3441058