• [bzoj3884] 上帝与集合的正确用法


    题意:要你算这个玩意额:(2^{2^{2^{...}}})

    题解:

    欧拉定理+递归

    (p=2^k*q (q为奇数))

    题目要求(2^{2^{2^{...}}}modp)

    变形为(2^k(2^{2^{2^{...}}-k}modq)) (这里需要在草稿纸上算一下)

    由于q是个奇数,那么肯定与2的指数互质

    原式变为(2^k(2^{(2^{2^{...}}-k)modphi(q)}modq))

    然后就可以递归求解了,当模数为1的时候,递归就结束了,然后就可以回溯计算了

    递归次数不超过(log_2p) ,单次求(phi(p))的复杂度为(sqrt{p})

    所以总复杂度为(T*log_2p*sqrt{p})

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    using namespace std;
    
    int gi() {
      int x=0,o=1; char ch=getchar();
      while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
      if(ch=='-') o=-1,ch=getchar();
      while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
      return o*x;
    }
    
    int get_phi(int x) {
      int ret=x;
      for(int i=2; i*i<=x; i++) {
        if(x%i==0) {
          ret=ret/i*(i-1);
          while(x%i==0) x/=i;
        }
      }
      if(x>1) ret=ret/x*(x-1);
      return ret;
    }
    
    int qpow(ll x, int y, int mo) {
      ll ret=1;
      while(y) {
        if(y&1) ret=ret*x%mo;
        x=x*x%mo,y>>=1;
      }
      return ret;
    }
    
    int solve(int p) {
      if(p==1) return 0;
      int k=0,phi,ret;
      while(!(p&1)) p>>=1,k++;//while(p是个偶数)
      phi=get_phi(p);
      ret=solve(phi);
      (ret+=phi-k%phi)%=phi;
      ret=qpow(2,ret,p)%p;
      return ret<<k;
    }
    
    int main() {
      int T=gi();
      while(T--) {
        int p=gi();
        printf("%d
    ", solve(p));
      }
      return 0;
    }
    
  • 相关阅读:
    洛谷P3620 [APIO/CTSC 2007] 数据备份
    洛谷P2744 量取牛奶
    洛谷P1560 蜗牛的旅行
    luogu P1776 宝物筛选_NOI导刊2010提高(02)
    luogu P1020 导弹拦截
    luogu P2015 二叉苹果树
    luogu P1137 旅行计划
    树形dp瞎讲+树形dp基础题题解
    luogu P1252 马拉松接力赛 P1803 凌乱的yyy / 线段覆盖
    luogu P1196 [NOI2002]银河英雄传说
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7617318.html
Copyright © 2020-2023  润新知