2019牛客多校 第九场 B.Quadratic equation

题意

    p = 1000000007.

   (x + y) % p = b

   (x * y) % p = c 

输入 b, c ,求 x,y,如果无解,输出-1 -1;

题意:

   求(x+y)² = b²          (x - y)² = b² - 4 * c

 因为有模p, 所以求 (b² - 4*c) 对p的二次剩余(意思为在短时间内求出x-y的值)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int k;
ll a,b,c,w;
ll p = 1000000007;
struct T{
	ll x,y;
};
T mul_two(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 qpow_two(T a,ll n,ll p){
   T ans;
   ans.x=1;
   ans.y=0;
   while(n){
      if(n&1) ans=mul_two(ans,a,p);
      n>>=1;
      a=mul_two(a,a,p);
   }
   return ans;
}
ll qpow(ll a,ll n,ll p){
   ll ans=1;
   a%=p;
   while(n){
      if(n&1) ans=ans*a%p;
      n>>=1;
      a=a*a%p;
   }
   return ans%p;
}
ll Legendre(ll a,ll p){
   return qpow(a,(p-1)>>1,p);
}
int solve(ll n,ll p){
   if(p==2) return 1;
   if(Legendre(n,p)+1==p) return -1;
   ll a,t;
   while(1){
      a=rand()%p;
      t=a*a-n;
      w=(t%p+p)%p;
      if(Legendre(w,p)+1==p) break;
   }
   T tmp;
   tmp.x=a;
   tmp.y=1;
   T ans=qpow_two(tmp,(p+1)>>1,p);
   return ans.x;
}
ll quick_pow(ll y){
   int b = p - 2;
   ll ans = 1;
   while(b){
      if(b % 2 == 1)
         ans = (ans * y) % p;
      y = (y * y )%p;
      b /= 2;
   }
   return ans % p;
}
int main(){
   scanf("%d",&k);
   while(k--){
      scanf("%lld%lld",&b,&c);
      a = (b*b%p-4*c) %p;
      if(a == 0){       // 当x == y 直接判断
      	if(b/2 * b/2 == c){
      		cout << b/2 << " " << b/2 << endl;
			}
			else{
				cout << -1 << " " << -1 << endl;
			}
			continue;
		}
		a = (a + p) % p;
      ll d = solve(a,p);   
      if(d == -1){       // 二次剩余为-1 时,无解
         printf("-1 -1\n");
         continue;
      }
      ll x = (b+d+p)%p*quick_pow(2);  // 因为除二,所以对2取逆元
      x = x % p;
      ll y = (b - x+p)%p;
      printf("%lld %lld\n",min(x, y),max(x, y));
   }
   return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值