• 扩展欧拉定理 [学习笔记]


    咕了好久…

    P4139 上帝与集合的正确用法

    对于 (b geq varphi(p)),有 (a^b = a^{b mod varphi(p) + varphi(p)} [mod p])

    其中 (gcd(a,p)) 没有要求,也就是可以不互质。

    有了这个式子, (2^{2^{2^{2^{2^{2^{2}}}}}} \% p) 就很好求了,递归就可以了,这里的指数 (2^{2^{2^{2^{2^{2}}}}} geq varphi(p)) 的,于是直接用就好了QAQ。递归不会超过 (log) 次,所以可以用递归就好了qwq。

    // by Isaunoya
    #include <bits/stdc++.h>
    using namespace std;
    
    #define rep(i, x, y) for (register int i = (x); i <= (y); ++i)
    #define Rep(i, x, y) for (register int i = (x); i >= (y); --i)
    
    const int _ = 1 << 21;
    struct I {
      char fin[_], *p1 = fin, *p2 = fin;
      inline char gc() {
        return (p1 == p2) && (p2 = (p1 = fin) + fread(fin, 1, _, stdin), p1 == p2) ? EOF : *p1++;
      }
      inline I& operator>>(int& x) {
        bool sign = 1;
        char c = 0;
        while (c < 48) ((c = gc()) == 45) && (sign = 0);
        x = (c & 15);
        while ((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15);
        x = sign ? x : -x;
        return *this;
      }
      inline I& operator>>(double& x) {
        bool sign = 1;
        char c = 0;
        while (c < 48) ((c = gc()) == 45) && (sign = 0);
        x = (c - 48);
        while ((c = gc()) > 47) x = x * 10 + (c - 48);
        if (c == '.') {
          double d = 1.0;
          while ((c = gc()) > 47) d = d * 0.1, x = x + (d * (c - 48));
        }
        x = sign ? x : -x;
        return *this;
      }
      inline I& operator>>(char& x) {
        do
          x = gc();
        while (isspace(x));
        return *this;
      }
      inline I& operator>>(string& s) {
        s = "";
        char c = gc();
        while (isspace(c)) c = gc();
        while (!isspace(c) && c != EOF) s += c, c = gc();
        return *this;
      }
    } in;
    struct O {
      char st[100], fout[_];
      signed stk = 0, top = 0;
      inline void flush() { fwrite(fout, 1, top, stdout), fflush(stdout), top = 0; }
      inline O& operator<<(int x) {
        if (top > (1 << 20)) flush();
        if (x < 0) fout[top++] = 45, x = -x;
        do
          st[++stk] = x % 10 ^ 48, x /= 10;
        while (x);
        while (stk) fout[top++] = st[stk--];
        return *this;
      }
      inline O& operator<<(char x) {
        fout[top++] = x;
        return *this;
      }
      inline O& operator<<(string s) {
        if (top > (1 << 20)) flush();
        for (char x : s) fout[top++] = x;
        return *this;
      }
    } out;
    
    #define pb emplace_back
    #define fir first
    #define sec second
    
    template <class T>
    inline void cmax(T& x, const T& y) {
      (x < y) && (x = y);
    }
    template <class T>
    inline void cmin(T& x, const T& y) {
      (x > y) && (x = y);
    }
    
    const int qwq = 1e7;
    int phi[qwq + 10];
    int qpow(int x, int y, int p) {
      int ans = 1;
      for (; y; y >>= 1, x = 1ll * x * x % p)
        if (y & 1) ans = 1ll * ans * x % p;
      return ans;
    }
    int solve(int p) { return (p == 1) ? 0 : qpow(2, solve(phi[p]) + phi[p], p); }
    signed main() {
    #ifdef _WIN64
      freopen("testdata.in", "r", stdin);
    #endif
      for (int i = 2; i <= qwq; i++) {
        if (phi[i]) continue;
        for (int j = i; j <= qwq; j += i) {
          if (!phi[j]) phi[j] = j;
          phi[j] = phi[j] / i * (i - 1);
        }
      }
      int T;
      in >> T;
      while (T--) {
        int p;
        in >> p;
        out << solve(p) << '
    ';
      }
      return out.flush(), 0;
    }
    

    CF906D Power Tower

    给定 (a { }) 让你求 (a_l ^ {a_{l+1} ^ {…^{a_r}}})

    然后你会发现 (varphi(x)) 在log层的时候会变成 1 ,所以暴力递归就好了,如果觉得慢,可以给 (varphi) 加个记忆化。

    // by Isaunoya
    #include <bits/stdc++.h>
    using namespace std;
    
    #define rep(i, x, y) for (register int i = (x); i <= (y); ++i)
    #define Rep(i, x, y) for (register int i = (x); i >= (y); --i)
    #define int long long
    
    const int _ = 1 << 21;
    struct I {
      char fin[_], *p1 = fin, *p2 = fin;
      inline char gc() {
        return (p1 == p2) && (p2 = (p1 = fin) + fread(fin, 1, _, stdin), p1 == p2) ? EOF : *p1++;
      }
      inline I& operator>>(int& x) {
        bool sign = 1;
        char c = 0;
        while (c < 48) ((c = gc()) == 45) && (sign = 0);
        x = (c & 15);
        while ((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15);
        x = sign ? x : -x;
        return *this;
      }
      inline I& operator>>(double& x) {
        bool sign = 1;
        char c = 0;
        while (c < 48) ((c = gc()) == 45) && (sign = 0);
        x = (c - 48);
        while ((c = gc()) > 47) x = x * 10 + (c - 48);
        if (c == '.') {
          double d = 1.0;
          while ((c = gc()) > 47) d = d * 0.1, x = x + (d * (c - 48));
        }
        x = sign ? x : -x;
        return *this;
      }
      inline I& operator>>(char& x) {
        do
          x = gc();
        while (isspace(x));
        return *this;
      }
      inline I& operator>>(string& s) {
        s = "";
        char c = gc();
        while (isspace(c)) c = gc();
        while (!isspace(c) && c != EOF) s += c, c = gc();
        return *this;
      }
    } in;
    struct O {
      char st[100], fout[_];
      signed stk = 0, top = 0;
      inline void flush() { fwrite(fout, 1, top, stdout), fflush(stdout), top = 0; }
      inline O& operator<<(int x) {
        if (top > (1 << 20)) flush();
        if (x < 0) fout[top++] = 45, x = -x;
        do
          st[++stk] = x % 10 ^ 48, x /= 10;
        while (x);
        while (stk) fout[top++] = st[stk--];
        return *this;
      }
      inline O& operator<<(char x) {
        fout[top++] = x;
        return *this;
      }
      inline O& operator<<(string s) {
        if (top > (1 << 20)) flush();
        for (char x : s) fout[top++] = x;
        return *this;
      }
    } out;
    
    #define pb emplace_back
    #define fir first
    #define sec second
    
    template <class T>
    inline void cmax(T& x, const T& y) {
      (x < y) && (x = y);
    }
    template <class T>
    inline void cmin(T& x, const T& y) {
      (x > y) && (x = y);
    }
    
    int n, m, q;
    vector<int> a;
    map<int, int> phi;
    
    int getphi(int x) {
      if (phi.count(x)) return phi[x];
      int res = x, qwq = x;
      for (int i = 2; i <= sqrt(x); ++i)
        if (!(x % i)) {
          res = res / i * (i - 1);
          while (!(x % i)) x /= i;
        }
      if (x > 1) res = res / x * (x - 1);
      return phi[qwq] = res;
    }
    int mod(int x, int p) { return (x < p) ? x : (x % p + p); }
    int qpow(int x, int y, int p) {
      int ans = 1;
      for (; y; y >>= 1, x = mod(x * x, p))
        if (y & 1) ans = mod(ans * x, p);
      return ans;
    }
    int dfs(int l, int r, int p) {
      if (l == r || p == 1) return mod(a[l], p);
      return qpow(a[l], dfs(l + 1, r, getphi(p)), p);
    }
    signed main() {
    #ifdef _WIN64
      freopen("testdata.in", "r", stdin);
    #endif
      in >> n >> m;
      a.resize(n);
      for (int i = 0; i < n; i++) in >> a[i];
      in >> q;
      while (q--) {
        int l, r;
        in >> l >> r;
        --l, --r;
        out << dfs(l, r, m) % m << '
    ';
      }
      return out.flush(), 0;
    }
    
  • 相关阅读:
    linux_shell_入门
    Linux下安装jdk
    Linux杂记
    Linux常用命令
    Java 性能优化的五大技巧
    Java异常处理的9个最佳实践
    Java面试:投行的15个多线程和并发面试题
    敏捷持续集成详解
    gitlab系列详解
    git系列讲解
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12457387.html
Copyright © 2020-2023  润新知