扩展欧拉定理
扩展欧拉定理
欧拉函数 \(\phi\)
设 \(\phi(x)\) 为 \([1, x]\) 范围内和 \(x\) 互质的数的数量.
对于质数 \(x\), 由于和 \([1, x - 1]\) 中任意数字互质, 所以有结论
对于正整数 \(x\), \(p_i\) 表示第 \(i\) 个质数, 由正整数的唯一分解设
由于被 \(p_i\) 整除的数有 \(x / p_i\) 个, 这些数一定不和 \(x\) 互质. 结合容斥原理, 对于所有的 \(p_i|x\), 和 \(x\) 互质的数有
提公因式:
整理得
设 \(x = ab\), \(gcd(a, b) = 1\)
把两式相乘
已知 \(p_i|a\) 和 \(p_i|b\) 不能同时满足, 又因为 \(x = ab\), 所以只要 \(p_i|b~or~p_i|a\), 当且仅当 \(p_i|x\), 上式变成
因此得出结论, 对于 \(x = ab\), \(gcd(a, b) = 1\), 有
我们把 \(\phi(x)\) 这种性质称作 积性函数
欧拉定理
设正整数 \(a\), \(p\) 互质
则
由此可以推得费马小定理, 即对于正整数 \(a\) 和质数 \(p\), 有
这就是快速幂求乘法逆元的原理
扩展欧拉定理
前置知识
- 引理一, 设正整数 \(x\), \(a_1\), \(a_2\), \(a_3\), ..., \(a_n\), 如果 \(x \equiv y (mod~a_i)\), 则有
 
- 引理二, 设质数 \(p\), 正整数 \(x > 1\), 则
 
证明
设正整数 \(q\), \(a\), \(x\), 质数 \(p\), 满足 \(x \geq \phi(p^q)\)
由于 \(p\) 是质数, 所以对于 \(gcd(a, p)\), 有两种情况, 即 \(1\) 或 \(p\).
- 针对 \(gcd(a, p) = 1\) 的情况, 一定有 \(gcd(a^x, p^q) = 1\), 根据欧拉定理, \(a^{\phi(p^q)}~\%~p^q= 1\), 所以一定有
 
- 针对 \(gcd(a, p) = p\) 的情况, 由引理二得 \(x \geq \phi(p^q) \geq q\). 一定有 \(a^x~\%~p^q = a^{\phi(p^q)}~\%~p^q = 0\). 所以
 
综上, 对于所有正整数 \(q\), \(a\), \(x\), 质数 \(p\), \((x \geq \phi(p^q))\), 有
设正整数 \(m\), 将其拆分为质因数对应幂的乘积, 由引理一和 \(\phi(x)\) 的积性函数性质得
因为 \(x \geq \phi(m)\), 所以对于所有 \(i\) 满足 \(p_i|m\), 有
因此
再次利用引理一, 得到
这就是扩展欧拉定理
模板 Luogu5091
求 \(a^b~\%~m\), \((1 \leq a \leq 10^9, 1 \leq b \leq 10^{2*10^7}, 1 \leq m \leq 10^8)\)
根据扩展欧拉定理
易证
所以 \(b\) 对 \(\phi(m)\) 取模, 可以在快读过程中不断取模避免高精
值得一提的是, 本题中可能出现 \(b < \phi(m)\) 的情况, 这时, \(a^{b~\%~\phi(m) + \phi(m)}\) 是错误的, 应该是 \(a^{b~\%~\phi(m)}\), 所以读入时也要判断 \(b\), \(m\) 的大小关系.
while (ch < '0' || ch > '9') {
  ch = getchar();
}
while (ch >= '0' && ch <= '9') {
  B *= 10;
  B += ch - '0';
  if(B > C) {
    flg = 1;
    B %= C;
  }
  ch = getchar();
}
关于求 \(phi(m)\), 由于只求一个数, 且 \(m \leq 10^8\), 所以线性筛就不好使了, 用下面的式子求出 \(phi(m)\) (先除后乘防溢出)
unsigned Phi(unsigned x) {
  unsigned tmp(x), anotherTmp(x), Sq(sqrt(x));
  for (register unsigned i(2); i <= Sq && i <= x; ++i) {
    if(!(x % i)) {
      while (!(x % i)) {
        x /= i;
      }
      tmp /= i;
      tmp *= i - 1;
    }
  }
  if (x > 1) {//存在大于根号 x 的质因数 
    tmp /= x;
    tmp *= x - 1;
  }
  return tmp;
}
这里要说明一下为什么枚举到 \(\sqrt{n}\), 把这些质因数除掉后剩下的 \(n'\) 一定是质数. 首先, \(n' \leq n\), 如果是合数, 一定存在因数 \(p\) 使得 \(p \leq \sqrt{n'} \leq \sqrt{n}\) 或 \(n'/p \leq \sqrt{n'} \leq \sqrt{n}\), 而这个 \(p\) 或 \(n'/p\) 至少有一个已经被枚举到了, 所以 \(n'\) 不可能是合数.
最后便是求乘积了, 用最普通的取模快速幂完成这个任务
unsigned Power(unsigned x, unsigned y) {
  if(!y) {
    return 1;
  }
  unsigned tmp(Power(x, y >> 1));
  tmp = ((long long)tmp * tmp) % D;
  if(y & 1) {
    return ((long long)tmp * x) % D;
  }
  return tmp;
}
最后是加了一点特判的完整 main()
int main() {
  A = RD();
  D = RD();
  C = Phi(D);
  while (ch < '0' || ch > '9') {
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    B *= 10;
    B += ch - '0';
    if(B > C) {
      flg = 1;
      B %= C;
    }
    ch = getchar();
  }
  if(B == 1) {
    printf("%u\n", A % D);
    return Wild_Donkey;
  }
  if(flg) {
    printf("%u\n", Power(A, B + C));
  }
  else {
    printf("%u\n", Power(A, B));
  }
  return Wild_Donkey;
}
                    
                
                
            
        
浙公网安备 33010602011771号