威尔逊定理

威尔逊定理:若p为素数,则p可以整除(p-1)!+1。

用同余方程表示为:(p-1)! ≡ -1 (mod p)

证明如下

充分性:

当p=1时,(p-1)! ≡ 0 (mod p)

当p=4时,(p-1)! ≡ 2 (mod p)

当p>4时,当p为完全平方数时,设k²=p,探讨2k和p的大小,因为k²-2k在k>2的时候永远大于0,所以p>2k>k,所以(p-1)! ≡ 1*2*......*k*......*2k*......*(p-1) ≡ 0 (mod p)

当p不为完全平方数时,设p=a*b,因为p>a>b,所以(p-1)! ≡ 1*2*......*a*......*b*......*(p-1) ≡ 0 (mod p)。

必要性:

当p=2时,(p-1)! ≡ -1 (mod p)

当p>2时,因为p为质数,则根据费马小定理存在a有pow(a,p-2),只要a与pow(a,p-2)不同余,则pow(a,p-2)为a的逆元。

假设二者同余,则有a²与pow(a,p-1)同余于1,解出来a=1或者p-1(x² ≡ 1(mod p)的解只有1和p-1,所以假设不成立,得证。

威尔逊定理的应用:

若存在n>p,要求计算 n! 中除了能被p整除的其他所有正整数相乘在模 p 的环境下,可以利用分块计算,每块为p的长度,前p-1项为(p-1)!,最后一项系数为出现第i个(p-1)!的意思,大概这样:

 所以最后只要计算利用威尔逊定理,再计算(n/p)! 和最后的尾巴部分就好了。时间复杂度为o(p+logp n)。

代码如下:

int factmod(int n, int p) {
  vector<int> f(p);
  f[0] = 1;
  for (int i = 1; i < p; i++) f[i] = f[i - 1] * i % p;
  int res = 1;
  while (n > 1) {
    if ((n / p) % 2) res = p - res;
    res = res * f[n % p] % p;
    n /= p;
  }
  return res;
}

 

 

 
posted @ 2023-08-13 20:45  DLSQS  阅读(255)  评论(0)    收藏  举报