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;
}

 

转载于:https://www.cnblogs.com/OIerLYF/p/7504243.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值