BZOJ 3884 上帝与集合的正确用法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3884 上帝与集合的正确用法相关的知识,希望对你有一定的参考价值。

学习借鉴了skywalkert大佬的题解 Orz

首先题目需要用到欧拉函数的一个性质

$\forall x\geq \phi(p)$

$a^x\equiv a^{x \; mod \; \phi(p) + \phi(p)}(mod\;p)$

设$f(p) = 2^{2^{2^{...}}}mod \; p$

$f(p)=2^{(2^{2^{...}} mod \; \phi(p)) + \phi(p)}mod \; p \\=2^{f(\phi(p)) + \phi(p)} mod \; p$

关于f(p)的递推式知道了,只要dfs就可以了。

时间复杂度$O(\sqrt{p}logp)$

map的作用就是记录取模x的时候的值

#include <cstdio>
#include <map>
using namespace std;

map<int,int>vis;

int pow(int x,int k,int p){
    int ans = 1;
    while(k){
        if(k&1) ans=(long long )ans*x%p;
        x = (long long)x * x % p;
        k>>=1;
    }
    return ans;
}

int phi(int x){
    int ans = x;
    for(int i=2;i*i<=x;i++){
        if(x%i==0){
            ans -= ans/i;
            while(x%i==0) x/=i;
        }
    }
    if(x>1) ans -= ans/x;
    return ans;
}

int dfs(int x){
    if(vis.count(x)) return vis[x];
    int p = phi(x);
    return vis[x] = pow(2,dfs(p)+p,x);
}

int main(){
    int t,n;
    scanf("%d",&t);
    vis[1]=0;
    while(t--){
        scanf("%d",&n);
        printf("%d\n",dfs(n));
    }
    return 0;
}

 

以上是关于BZOJ 3884 上帝与集合的正确用法的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3884 上帝与集合的正确用法

BZOJ3884上帝与集合的正确用法 欧拉定理

欧拉函数 BZOJ3884 上帝与集合的正确用法

BZOJ3884: 上帝与集合的正确用法

BZOJ3884: 上帝与集合的正确用法

Bzoj3884 上帝与集合的正确用法