题目描述
Amy asks Mr. B problem B. Please help Mr. B to solve the following problem.
Let p = 1000000007.
Given two integers b and c, please find two integers x and y(0≤x≤y<p)(0 leq x leq y < p)(0≤x≤y<p), such that
(x+y) mod p=b(x + y) mod p = b(x+y)modp=b
(x×y) mod p=c(x imes y) mod p = c(x×y)modp=c
输入描述:
The first line contains an integer t, which is the number of test cases (1 <= t <= 10).
In the following t lines, each line contains two integers b and c (0 <= b, c < p).
输出描述:
For each test case, please output x, y in one line.
If there is a solution, because x <= y, the solution is unique.
If there is no solution, please output -1, -1
示例1
输出
复制2 2 2 3 -1 -1 5 5 10000 10000 474848249 525151758 352077071 647922939 448762649 551237578 -1 -1 366417496 633582504
解题报告:这道题目一开始很容易就想到要去求解x-y,但是呢简单的求解根据b*b-4*c是错误的,因为咱们没有办法去判断是否存在解,后来想到了一个定理
就是二次剩余定理,但是奈何实力弱,只能判断出来是否存在解的情况,没有办法去实现二次剩余定理的答案的求解,最后隔壁队给了一个能够看懂得板子,才
成功得求出答案,然后因为是(x+y)%mod = b,x>=0&&x<mod y>=0&&y<mod ,所以x+y存在两种答案,一种就是 x+y=b 另一种就是(x+y)=mod+b; 使用
二次剩余定理会出现两个解,所以也需要去进行讨论,一共存在四种情况,进行一下分类讨论,判定一下每组x,y的解的范围和正确性,需要非常注意的就是咱们
的答案是根据(x+y)%mod=b实现的,而(x*y)%mod ==c 的条件没有使用,所以在这个判断的时候就需要去使用一下,否则就会疯狂wa,and每组解的求解的时
候不需要再进行取余处理了,这个时候的解就不再是mod 的情况了,而是本身就是这个等式。
ac代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef long long ll; 8 9 const ll mod=1e9+7; 10 11 int t; 12 ll b,c; 13 14 ll qpow(ll a,ll b,ll p){ 15 ll ans=1; 16 while(b){ 17 if(b&1) ans=ans*a%p; 18 a=a*a%p; 19 b>>=1; 20 } 21 return ans; 22 } 23 ll modsqr(ll a,ll n){ 24 ll b,k,i,x; 25 if(n==2) return a%n; 26 if(qpow(a,(n-1)/2,n) == 1){ 27 if(n%4 == 3){ 28 x=qpow(a,(n+1)/4,n); 29 } 30 else{ 31 for(b=1; qpow(b,(n-1)/2,n) == 1; b++); 32 i = (n-1)/2; 33 k=0; 34 while(i%2==0){ 35 i /= 2,k /= 2; 36 if((qpow(a,i,n)*qpow(b,k,n)+1)%n == 0) k += (n-1)/2; 37 } 38 x = qpow(a,(i+1)/2,n)*qpow(b,k/2,n)%n; 39 } 40 if(x*2 > n) x = n-x; 41 return x; 42 } 43 return -1; 44 } 45 46 int main() 47 { 48 cin>>t; 49 while(t--) 50 { 51 cin>>b>>c; 52 ll tmp1=(b*b-4*c+4*mod)%mod; 53 ll flag=modsqr(tmp1,mod); 54 if(b*b-4*c==0) 55 flag=0; 56 if(flag==-1)//二次剩余判断是否有解 57 { 58 cout<<"-1 -1"<<endl; 59 continue; 60 } 61 else 62 { 63 ll tmp=mod-flag; 64 ll y1=(b+flag)/2; 65 ll x1=(b-flag)/2; 66 //cout<<x1<<" "<<y1<<endl; 67 ll y2=(b+tmp)/2; 68 ll x2=(b-tmp)/2; 69 ll y3=(mod+b+flag)/2; 70 ll x3=(mod+b-flag)/2; 71 ll y4=(2*mod+b-flag)/2; 72 ll x4=(b+flag)/2; 73 74 if(x1<=y1&&x1<mod&&x1>=0&&y1<mod&&y1>=0&&(x1*y1)%mod==c) 75 { 76 cout<<x1<<" "<<y1<<endl; 77 } 78 else if(x2<=y2&&x2<mod&&x2>=0&&y2<mod&&y2>=0&&(x2*y2)%mod==c) 79 { 80 cout<<x2<<" "<<y2<<endl; 81 } 82 else if(x3<=y3&&x3<mod&&x3>=0&&y3<mod&&y3>=0&&(x3*y3)%mod==c) 83 { 84 cout<<x3<<" "<<y3<<endl; 85 } 86 else if(x4<=y4&&x4<mod&&x4>=0&&y4<mod&&y4>=0&&(x4*y4)%mod==c) 87 { 88 cout<<x4<<" "<<y4<<endl; 89 } 90 else 91 { 92 cout<<"-1 -1"<<endl; 93 } 94 } 95 } 96 }