二次剩余

mac2024-11-28  41

二次剩余

二次剩余勒让德符号判别式求解流程模板2019牛客第九场 B Quadratic equation

二次剩余

定义:对于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)