zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    Linux下端口被占用确认
    Debuggex – 超好用的正则表达式可视化调试工具
    URL最大长度
    无需重启 修改计算机名直接生效
    UDP穿越NAT原理(p2p)
    gdb中信号
    锁 (读写锁优先级 写饥饿) (锁竞争引发的高系统调用)
    Loopback接口用途---用作管理地址。
    C/C++调试:gdbserver的简单使用
    总结一下NDK crash排查步骤
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7617318.html
Copyright © 2011-2022 走看看