二次剩余

二次剩余

定义:对于n、p,若存在x,使得 x 2 ≡ n ( m o d   p ) x^2\equiv n(mod\ p) x2n(mod p),则称n为模p意义下的二次剩余。
也就是说,如果n是模p的二次剩余。那么 n   m o d   p \sqrt n\ mod\ p n  mod p,可以用二次同余方程的解 x x x 来代替 n \sqrt n n ,暴力地找就是 x 2 % p = = n x^2\%p==n x2%p==n

勒让德符号

( n p ) = { 1 n 是 模 p 意 义 下 的 二 次 剩 余 − 1 n 是 模 p 意 义 下 的 二 次 非 剩 余 0 n ≡ 0 ( m o d   p ) (\frac np)=\begin{cases} 1 & n是模p意义下的二次剩余 \\ -1 &n是模p意义下的二次非剩余\\ 0& n\equiv 0 (mod\ p) \end{cases} (pn)=110npnpn0(mod p)

判别式

( n p ) ≡ n p − 1 2 ( m o d   p ) (\frac np)\equiv n^{\frac {p-1}2} (mod\ p) (pn)n2p1(mod p)

p 的二次剩余和二次非剩余的个数均为 p − 1 2 \frac {p−1}2 2p1(不考虑0)的情况下

求解流程

1、先用判定式,判别式是否二次剩余,不是就返回-1
2、然后随机找一个a,使得 a 2 − x a^2-x a2x是模p的二次非剩余
3、设 w ≡ a 2 − x ( m o d   p ) w\equiv a^2-x (mod\ p) wa2x(mod p),则 x ≡ ( a + w ) p + 1 2 x\equiv(a+\sqrt w)^{\frac {p+1}2} x(a+w )2p+1就是二次同余方程的解

模板

需要保证调用函数 solve(n,p) 的数是正整数

mt19937_64 gen(time(0));
ll w;
struct T
{
    ll x,y;
};
T mul(T a,T b,ll p)
{
    T ans;
    ans.x=(a.x*b.x%p+a.y*b.y%p*w%p)%p;
    ans.y=(a.x*b.y%p+a.y*b.x%p)%p;
    return ans;
}
T qpow2(T base,ll n,ll mod)
{
    T ret={1,0};
    while(n)
    {
        if(n&1) ret=mul(ret,base,mod);
        n>>=1;
        base=mul(base,base,mod);
    }
    return ret;
}
ll qpow(ll base,ll n,ll mod)
{
    ll ret=1;
    base%=mod;
    while(n)
    {
        if(n&1) ret=ret*base%mod;
        n>>=1;
        base=base*base%mod;
    }
    return ret;
}
ll Legendre(ll n,ll p)
{
    return qpow(n,(p-1)>>1,p);
}
ll solve(ll n,ll p)
{
    if (n==0) return 0;
    if (n==1) return 1;
    if(Legendre(n,p)+1==p) return -1;
    ll a;
    while(1)
    {
        a=gen()%p;
        w=((a*a-n)%p+p)%p;
        if(Legendre(w,p)+1==p) break;
    }
    T tmp={a,1};
    T ans=qpow2(tmp,(p+1)>>1,p);
    return ans.x;
}

2019牛客第九场 B Quadratic equation

链接:https://ac.nowcoder.com/acm/contest/889/B

题意:给出 b、c 的值,求 x 、y 的解,如果不存在则输出 -1 -1
( x + y ) ≡ b ( m o d    p ) (x+y) \equiv b (\mod p) (x+y)b(modp)
x y ≡ c ( m o d    p ) xy\equiv c (\mod p) xyc(modp)

#include <bits/stdc++.h>
#define ll long long 
using namespace std;
const int mod=1e9+7;

mt19937_64 gen(time(0));
ll w;
struct T
{
    ll x,y;
};
T mul(T a,T b,ll p)
{
    T ans;
    ans.x=(a.x*b.x%p+a.y*b.y%p*w%p)%p;
    ans.y=(a.x*b.y%p+a.y*b.x%p)%p;
    return ans;
}
T qpow2(T base,ll n,ll mod)
{
    T ret={1,0};
    while(n)
    {
        if(n&1) ret=mul(ret,base,mod);
        n>>=1;
        base=mul(base,base,mod);
    }
    return ret;
}
ll qpow(ll base,ll n,ll mod)
{
    ll ret=1;
    base%=mod;
    while(n)
    {
        if(n&1) ret=ret*base%mod;
        n>>=1;
        base=base*base%mod;
    }
    return ret;
}
ll Legendre(ll n,ll p)
{
    return qpow(n,(p-1)>>1,p);
}
 
ll solve(ll n,ll p)
{
    if (n==0) return 0;
    if (n==1) return 1;
    if(Legendre(n,p)+1==p) return -1;
    ll a;
    while(1)
    {
        a=gen()%p;
        w=((a*a-n)%p+p)%p;
        if(Legendre(w,p)+1==p) break;
    }
    T tmp={a,1};
    T ans=qpow2(tmp,(p+1)>>1,p);
    return ans.x;
}
ll t,b,c; 
int inv2=qpow(2,mod-2,mod);
int main()
{
	scanf("%lld",&t);
	while(t--)
	{
		scanf("%lld%lld",&b,&c);
		ll res=b*b%mod-4*c%mod;
		res=(res+mod)%mod;
		res=solve(res,mod);
		if(res==-1)
		{
			puts("-1 -1");
			continue;
		}
		ll x=(b-res)*inv2%mod,y=(b+res)*inv2%mod;
		x=(x+mod)%mod;
		if(x>y) swap(x,y);
		printf("%lld %lld\n",x,y);
	}
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值