BZOJ 3884 上帝与集合的正确用法【欧拉函数】

题目链接:

http://www.lydsy.com/JudgeOnline/problem.php?id=3884

题意:

定义$f(p)=2^{2^{2^{2^{…^2}}}}(\ mod \ p)$,求$f(p)$,其中$2$有无穷多个,$1 \leq p \leq 10^{7}$。

分析:

已知$$a^b\%p=(a\%p)^{\phi(p) + b \% \phi(p)} \% p$$
那么$$f(p)=(2 \% p)^{2^{2^{2^{…^2}}}\%\phi(p)+\phi(p)}\% p$$
即$$f(p)=(2\%p)^{f(\phi(p))+\phi(p)} \% p$$
根据 $n为奇数,\phi(2n)=\phi(n),n为偶数,\phi(2n)=2\phi(n)$,总是可以转化成一半处理,在$O(logp)$内变为$1$,$f(1)=0$,递归截止。
加上因式分解求欧拉函数总体时间复杂度$O(logp\sqrt p)$。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/*************************************************************************
> File Name: 3884.cpp
> Author: jiangyuzhu
> Mail: 834138558@qq.com
> Created Time: 2016/8/30 19:08:42
************************************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
int euler(int n)
{
int res = n;
for(int i = 2; i * i <= n; i++){
if(n % i == 0){
res = res / i * (i - 1);
while(n % i == 0) n /= i;
}
}
if(n != 1) res = res / n * (n - 1);
return res;
}
int quick_pow(int b, int a, int p)
{
ll res = 1;
for(; a; a >>= 1, b = b * 1ll * b % p){
if(a & 1) res = res * 1ll * b % p;
}
return res;
}
int a2;
int dfs(int p)
{
if(p == 1) return 0;
int np = euler(p);
return quick_pow(a2, dfs(np) + np, p);
}
int main (void)
{
int T;scanf("%d", &T);
while(T--){
int p;scanf("%d", &p);
a2 = 2 % p;
printf("%d\n", dfs(p));
}
return 0;
}
文章目录
  1. 1. 题目链接:
  2. 2. 题意:
  3. 3. 分析:
  4. 4. 代码: