牛客多校九B
给定
$(x+y)\%mod=b$
$(x*y)\%mod=c$
求 $x,y$
二次剩余
求$((x-y)^{2})\%mod = (b\times b-4\times c)\%mod$
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1000000007; ll qp(ll a, ll b, ll c) { ll ans = 1; while (b) { if (b % 2 == 1)ans = (ans*a) % c; b /= 2; a = (a*a) % c; } return ans; } ll p=mod; ll w;//二次域的D值 bool ok;//是否有解 struct QuadraticField//二次域 { ll x, y; QuadraticField operator*(QuadraticField T)//二次域乘法重载 { QuadraticField ans; ans.x = (this->x*T.x%p + this->y*T.y%p*w%p) % p; ans.y = (this->x*T.y%p + this->y*T.x%p) % p; return ans; } QuadraticField operator^(ll b)//二次域快速幂 { QuadraticField ans; QuadraticField a = *this; ans.x = 1; ans.y = 0; while (b) { if (b & 1) { ans = ans*a; b--; } b /= 2; a = a*a; } return ans; } }; ll Legender(ll a)//求勒让德符号 { ll ans=qp(a, (p - 1) / 2, p); if (ans + 1 == p)//如果ans的值为-1,%p之后会变成p-1。 return -1; else return ans; } ll Getw(ll n, ll a)//根据随机出来a的值确定对应w的值 { return ((a*a - n) % p + p) % p;//防爆处理 } ll solve(ll n) { ll a; if(n==0) return 0; if (p == 2)//当p为2的时候,n只会是0或1,然后0和1就是对应的解 return n; if (Legender(n) == -1)//无解 ok = false; srand((unsigned)time(NULL)); while (1)//随机a的值直到有解 { a = rand()%p; w = Getw(n, a); if (Legender(w) == -1) break; } QuadraticField ans,res; res.x = a; res.y = 1;//res的值就是a+根号w ans = res ^ ((p + 1) / 2); return ans.x; } int main() { ll q; scanf("%lld",&q); ll a,b,n,ans1,ans2; ll inv2=qp(2,mod-2,mod); while (q--) { scanf("%lld%lld",&a,&b); ok = true; n=(a*a%mod-4*b%mod+mod)%mod; ans1 = solve(n); ans2 = p - ans1;//一组解的和是p if (!ok) { cout<<-1<<' '<<-1<<'\n'; } else { ll x=(ans1+a)%p*inv2%p; ll y=(a-x+p)%p; printf("%lld %lld\n", min(x,y),max(x,y) ); } } }