【BZOJ 3884】上帝与集合的正确用法(新知识)

【题目描述】

根据一些书上的记载,上帝的一次失败的创世经历是这样的:
第一天, 上帝创造了一个世界的基本元素,称做“元”。
第二天, 上帝创造了一个新的元素,称作“α”。“α”被定义为“元”构成的集合。容易发现,一共有两种不同的“α”。
第三天, 上帝又创造了一个新的元素,称作“β”。“β”被定义为“α”构成的集合。容易发现,一共有四种不同的“β”。
第四天, 上帝创造了新的元素“γ”,“γ”被定义为“β”的集合。显然,一共会有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)} abab 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=222mod 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));
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值