【題目描述】
根據一些書上的記載,上帝的一次失敗的創世經歷是這樣的:
第一天, 上帝創造了一個世界的基本元素,稱做“元”。
第二天, 上帝創造了一個新的元素,稱作“α”。“α”被定義爲“元”構成的集合。容易發現,一共有兩種不同的“α”。
第三天, 上帝又創造了一個新的元素,稱作“β”。“β”被定義爲“α”構成的集合。容易發現,一共有四種不同的“β”。
第四天, 上帝創造了新的元素“γ”,“γ”被定義爲“β”的集合。顯然,一共會有16種不同的“γ”。
如果按照這樣下去,上帝創造的第四種元素將會有65536種,第五種元素將會有2^65536種。這將會是一個天文數字。
然而,上帝並沒有預料到元素種類數的增長是如此的迅速。他想要讓世界的元素豐富起來,因此,日復一日,年復一年,他重複地創造着新的元素……
然而不久,當上帝創造出最後一種元素“θ”時,他發現這世界的元素實在是太多了,以致於世界的容量不足,無法承受。因此在這一天,上帝毀滅了世界。
至今,上帝仍記得那次失敗的創世經歷,現在他想問問你,他最後一次創造的元素“θ”一共有多少種?
上帝覺得這個數字可能過於巨大而無法表示出來,因此你只需要回答這個數對p取模後的值即可。
你可以認爲上帝從“α”到“θ”一共創造了,或次,或者乾脆次。
一句話題意
【分析】
對於此題有一個重要的結論:
當時,有
由於本題指數可被認爲無窮大,所以可以直接使用上面結論。
於是令,則:
【代碼】
#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));
}
}