2019牛客暑期多校训练营(第九场)Quadratic equation——二次剩余(模奇素数)&&Cipolla算法
题意
给定模 $p = 1000000007$ 和 $b,c$,求 $x$ 和 $y$($0\leq x\leq y< p$),其中 $x$ 和 $y$ 满足,
$(x + y) mod \ p = b$
$(x * y) mod \ p = c$
分析
根据模的性质,可化成 $(2x-b)^2 \equiv b^2-4c(mod \ p)$,然后核心问题是解 $x^2 \equiv a(mod\ p)$ 这个方程,直接上模板吧。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll p=1e9+7; const ll inv2 = 500000004; struct hh{ ll x,y; hh(){}; hh(ll _x,ll _y){ x=_x;y=_y; } }; ll w; hh mul(hh a,hh b,ll p){ hh 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; } hh quick1(hh a,ll b,ll p){ hh ans=hh(1,0); while(b){ if(b&1) ans=mul(ans,a,p); a=mul(a,a,p); b>>=1; } return ans; } ll quick2(ll a,ll b,ll p){ ll ans=1; while(b){ if(b&1) ans=(ans*a)%p; b>>=1; a=(a*a)%p; } return ans; } ll solve(ll a,ll p){//求解 x^2=a(mod p) 的x的值,无解返回-1 a = (a%p + p)%p;//注意这句话 if(a==0) return 0;//注意这句话 if(p==2) return a; if(quick2(a,(p-1)/2,p)==p-1) return -1; ll b,t; while(1){ b=rand()%p; t=b*b-a; w=(t%p+p)%p; if(quick2(w,(p-1)/2,p)==p-1) break; } hh ans=hh(b,1); ans=quick1(ans,(p+1)/2,p); return ans.x; } ll b, c; int main() { int T; scanf("%d", &T); while(T--) { scanf("%lld%lld", &b, &c); ll two = solve(b*b-4*c, p); if(two == -1) printf("-1 -1\n"); else { ll x = (b+two) * inv2 % p; ll y = (b-x+p) % p; if(x > y) swap(x, y); printf("%lld %lld\n", x, y); } } return 0; }
个性签名:时间会解决一切