二次剩余小记 更新于 2026/7/10 08:43:43 作者

command_block

P.S 本文只探讨模数pp奇质数的情况。

目标/定义

求解 x2=c(mod p)\large{x^2=c(mod\ p)} 这个方程组。

如果方程有解,则称cc是模pp二次剩余,否则称作二次非剩余。

(下面默认在模pp的剩余系下讨论)

欧拉判别法

给定c,pc,p,如何判定 x2=cx^2=c 是否有解呢?

结论:\color{blue}\text{结论:} $c^{\large{\frac{p-1}{2}}}=\begin{cases}\ \ \ 1\rightarrow\text{有解}\\ -1\rightarrow\text{无解}\end{cases}$

证明:\color{blue}\text{证明:}

  • 引理1.1\color{blue}1.1 : cp12=±1c^{\large{\frac{p-1}{2}}}=±1

由费马小定理得(cp12)2=cp1=1(c^{\large{\frac{p-1}{2}}})^2=c^{p-1}=1,可得cp12=±1c^{\large{\frac{p-1}{2}}}=±1

  • 引理1.2\color{blue}1.2 cp12=1cc^{\large{\frac{p-1}{2}}}=-1 \Rightarrow c不是二次剩余

采用反证法,假设有x2=cx^2=c,可得cp12=xp1=1c^{\large{\frac{p-1}{2}}}=x^{p-1}=-1

与费马小定理矛盾,原命题得证。

  • 引理1.3\color{blue}1.3 cp12=1cc^{\large{\frac{p-1}{2}}}=-1 \Leftarrow c不是二次剩余

假设有x2=cx^2=c,但是xx不是同余系里面的数,可以视为虚数,只满足x2=cx^2=c这一条性质。

由于xx不是同余系内的数,必定不满足费马小定理,可得xp11x^{p-1}≠1,那么只能是1-1了。

(费马小定理对且只对同余系生效)

综上三个引理可以逻辑推导出欧拉判别法,证毕。

二次剩余的个数

结论:\color{blue}\text{结论:}pp下的二次剩余恰有p12\dfrac{p-1}{2}个。

  • 引理 : c2=(pc)2c^2=(p-c)^2

显然成立,由此可得,如果x2=cx^2=c有解,则必然有两解。

证明:\color{blue}\text{证明:}

任选两个数x,y(xy)x,y(x≠y),且x2=y2x^2=y^2

那么(x+y)(xy)=0(x+y)(x-y)=0,即p(x+y)(xy)p|(x+y)(x-y),

显然p(xy)p|(x-y)不成立,那么p(x+y)p|(x+y),即x+y=0x+y=0

那么,对于一个xx,和它平方相同的有且仅有另外一个yy

总共有p12\dfrac{p-1}{2}个不同的平方,那么二次剩余,二次非剩余各有p12\dfrac{p-1}{2}个。

Cipolla算法

现在真正来求解x2=c(mod p)x^2=c(mod\ p)

首先判定方程是否无解(如果c=0c=0则输出0)

如果有解,我们任意找一个aa,使得a2ca^2-c二次非剩余

方法:不断随机然后判定。根据上文内容,期望随机次数22次。

w2=(a2c)w^2=(a^2-c),注意ww不是同余系里面的数,可以理解为虚数,只有w2=(a2c)w^2=(a^2-c)这一条性质。

我们扩系,把每个数变成a+bwa+bw的形式,重载运算。容易证明扩系之后仍然是环。

P.Ss=w2=(a2c)s=w^2=(a^2-c)

$(x_1+y_1w)*(x_2+y_2w)=(x_1x_2+y_1y_2s)+(x_1y_2+x_2y_1)w$

那么c=(a+w)p+1c=(a+w)^{p+1},所以x=(a+w)p+12x=(a+w)^{\frac{p+1}{2}}

  • 引理3.1\color{blue}3.1 (a+b)p=ap+bp(a+b)^p=a^p+b^p

    二项式展开可得 : $(a+b)^p=\sum\limits_{i=0}^p\dbinom{i}{p}a^{i}b^{p-i}$

    由卢卡斯定理 : $\dbinom{i}{p}=\dbinom{i/p}{p/p}\dbinom{i\%p}{p\%p}=\dbinom{i/p}{1}\dbinom{i\%p}{0}$

    这个式子只在i=0i=0或者pp的时候值为1,否则为0.

    所以(a+b)p=ap+bp(a+b)^p=a^p+b^p

  • 引理3.2\color{blue}3.2 wp=ww^p=-w

    wp=wp1w=(a2c)p12ww^p=w^{p-1}w=(a^2-c)^{\large{\frac{p-1}{2}}}w

    由欧拉判别法,(a2c)p12=1(a^2-c)^{\large{\frac{p-1}{2}}}=-1,证毕。

那么 :

(a+w)p+1=(ap+wp)(a+w)=(a+w)(aw)(a+w)^{p+1}=(a^p+w^p)(a+w)=(a+w)(a-w)

=a2w2=a2a2+c=c=a^2-w^2=a^2-a^2+c=c

正确性得证。

P5491 【模板】二次剩余

#include<algorithm>
#include<cstdio>
#define ll long long
using namespace std;
int mod,c;
ll powM(ll a,int t)
{
  ll ans=1;
  while(t){
	  if (t&1)ans=ans*a%mod;
	  a=a*a%mod;
	  t>>=1;
  }return ans;
}
ll sav;
struct Mcp
{ 
  ll x,y;
  Mcp operator * (Mcp const& B) const
  {return (Mcp){(x*B.x+y*B.y%mod*sav)%mod,(x*B.y+y*B.x)%mod};}
};
Mcp powM(Mcp a,int t)
{
  Mcp ans=(Mcp){1,0};
  while(t){
	  if (t&1)ans=ans*a;
	  a=a*a;
	  t>>=1;
  }return ans;
}
void solve()
{
  scanf("%d%d",&c,&mod);
  if (c==0)
    {puts("0");return ;}
  if (powM(c,(mod-1)/2)==mod-1)
    {puts("Hola!");return ;}
  int a;
  while(1){
    a=(rand()%(mod-1)+mod)%(mod-1)+1;
    sav=(1ll*a*a-c+mod)%mod;
    if (powM(sav,(mod-1)/2)==mod-1){
      Mcp W=(Mcp){a,1};
      W=powM(W,(mod+1)/2);
      ll x1=W.x,x2=mod-W.x;
      if (x1>x2)swap(x1,x2);
      printf("%lld %lld\n",x1,x2);
      break;
    }
  }
}
int main()
{
  int T;
  scanf("%d",&T);
  while(T--)solve();
  return 0;
}