【题目描述】
根据一些书上的记载,上帝的一次失败的创世经历是这样的:
第一天, 上帝创造了一个世界的基本元素,称做“元”。
第二天, 上帝创造了一个新的元素,称作“α”。“α”被定义为“元”构成的集合。容易发现,一共有两种不同的“α”。
第三天, 上帝又创造了一个新的元素,称作“β”。“β”被定义为“α”构成的集合。容易发现,一共有四种不同的“β”。
第四天, 上帝创造了新的元素“γ”,“γ”被定义为“β”的集合。显然,一共会有16种不同的“γ”。
如果按照这样下去,上帝创造的第四种元素将会有65536种,第五种元素将会有2^65536种。这将会是一个天文数字。
然而,上帝并没有预料到元素种类数的增长是如此的迅速。他想要让世界的元素丰富起来,因此,日复一日,年复一年,他重复地创造着新的元素……
然而不久,当上帝创造出最后一种元素“θ”时,他发现这世界的元素实在是太多了,以致于世界的容量不足,无法承受。因此在这一天,上帝毁灭了世界。
至今,上帝仍记得那次失败的创世经历,现在他想问问你,他最后一次创造的元素“θ”一共有多少种?
上帝觉得这个数字可能过于巨大而无法表示出来,因此你只需要回答这个数对p取模后的值即可。
你可以认为上帝从“α”到“θ”一共创造了
1
0
9
次
元
素
10^9次元素
109次元素,或
1
0
18
10^{18}
1018次,或者干脆
∞
∞
∞次。
一句话题意
【分析】
对于此题有一个重要的结论:
当
b
>
φ
(
c
)
b>\varphi(c)
b>φ(c)时,有
a
b
≡
a
b
m
o
d
φ
(
c
)
+
c
(
m
o
d
c
)
a^b\equiv a^{b\space mod \space \varphi(c)+c}\qquad \small{(mod\space c)}
ab≡ab mod φ(c)+c(mod c)
由于本题指数可被认为无穷大,所以可以直接使用上面结论。
于是令
f
(
i
)
=
2
2
2
⋯
f(i)=2^{2^{2^{\cdots}}}
f(i)=222⋯,则:
f
(
i
)
m
o
d
p
=
2
2
2
⋯
m
o
d
p
=
2
(
2
2
2
⋯
m
o
d
φ
(
p
)
+
p
)
m
o
d
p
=
2
f
(
φ
(
p
)
)
+
p
f
(
1
)
=
0
f(i)\space \small{mod} \space p = 2^{2^{2^{\cdots}}} \small{mod} \space p = 2^{(2^{2^{2^{\cdots}}}\space mod \space \varphi(p)+p)}\space \small{mod} \space p=2^{f(\varphi(p))+p} \newline \newline f(1)=0
f(i) mod p=222⋯mod p=2(222⋯ mod φ(p)+p) mod p=2f(φ(p))+pf(1)=0
【代码】
#include<bits/stdc++.h>
#define ll long long
using namespace std;
map<int, ll> res;
inline ll ksm(ll a, ll b, ll p)
{
ll ret = 1;
while(b)
{
if(b & 1) (ret *= a) %= p;
(a *= a) %= p, b >>= 1;
}
return ret;
}
inline ll phi(int x)
{
ll ret = x;
for(ll i = 2; i * i <= x; i++)
{
if(x % i == 0)
{
while(x % i == 0) x /= i;
ret /= i, ret *= i - 1;
}
}
if(x > 1) ret /= x, ret *= x - 1;
return ret;
}
ll calc(int c)
{
if(res.count(c)) return res[c];
int ph = phi(c);
return res[c] = ksm(2, calc(ph) + ph, c);
}
int main()
{
int T, n;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
printf("%lld\n", calc(n));
}
}