二次剩余小记
command_block · · 个人记录
P.S 本文只探讨模数
目标/定义
求解
如果方程有解,则称
(下面默认在模
欧拉判别法
给定
- 引理
\color{blue}1.1 :c^{\large{\frac{p-1}{2}}}=±1
由费马小定理得
- 引理
\color{blue}1.2 c^{\large{\frac{p-1}{2}}}=-1 \Rightarrow c 不是二次剩余
采用反证法,假设有
与费马小定理矛盾,原命题得证。
- 引理
\color{blue}1.3 c^{\large{\frac{p-1}{2}}}=-1 \Leftarrow c 不是二次剩余
假设有
由于
(费马小定理对且只对同余系生效)
综上三个引理可以逻辑推导出欧拉判别法,证毕。
二次剩余的个数
显然成立,由此可得,如果
任选两个数
那么
显然
那么,对于一个
总共有
Cipolla算法
现在真正来求解
首先判定方程是否无解(如果
如果有解,我们任意找一个
方法:不断随机然后判定。根据上文内容,期望随机次数
设
我们扩系,把每个数变成
P.S 设
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
那么
-
引理
\color{blue}3.1 (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=0 或者p 的时候值为1,否则为0.所以
(a+b)^p=a^p+b^p -
引理
\color{blue}3.2 w^p=-w w^p=w^{p-1}w=(a^2-c)^{\large{\frac{p-1}{2}}}w 由欧拉判别法,
(a^2-c)^{\large{\frac{p-1}{2}}}=-1 ,证毕。
那么 :
正确性得证。
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;
}