test20181020 B君的第一题

题意


分析

二次剩余问题。

x,y相当于二次方程

\[x^2-bx+c=0 \mod{p} \]

的两根。

摸意义下的二次方程仍然考虑判别式\(\Delta=b^2-4c\)

它能开根的条件是\(\Delta=0\)\(\Delta^{\frac{p-1}{2}}=1\)

若能开根,则根为\(\Delta^{\frac{p+1}{4}}\)

然后就是普通的解一元二次方程了。

代码

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#include<cassert>
#define rg register
#define il inline
#define co const
#pragma GCC optimize ("O0")
using namespace std;
template<class T> il T read()
{
    T data=0;
	int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
		if(ch=='-')
			w=-1;
		ch=getchar();
	}
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return data*w;
}
template<class T> il T read(T&x)
{
	return x=read<T>();
}
typedef long long ll;
const int INF=0x7fffffff;

const int mod=1e9+7;

int qpow(int x,int k)
{
	int res=1;
	while(k)
	{
		if(k&1)
			res=(ll)res*x%mod;
		x=(ll)x*x%mod,k>>=1;
	}
	return res;
}

int main()
{
  freopen("lanzhou.in","r",stdin);
  freopen("lanzhou.out","w",stdout);
	int T;
	read(T);
	while(T--)
	{
		int b=read<int>(),c=read<int>();
		int d=((ll)b*b-(ll)4*c)%mod;
		if(d<0)
		{
			d+=mod;
		}
//		cerr<<"d="<<d<<endl;
		if(d!=0&&qpow(d,(mod-1)/2)!=1)
		{
			puts("-1 -1");
		}
		else
		{
			int r=qpow(d,(mod+1)/4);
			assert((ll)r*r%mod==d);
			int x=(ll)(b+r)*qpow(2,mod-2)%mod;
			int y=(ll)(b-r)*qpow(2,mod-2)%mod;
			if(x<0)
			{
				x+=mod;
			}
			if(y<0)
			{
				y+=mod;
			}
			if(x>y)
			{
				swap(x,y);
			}
			printf("%d %d\n",x,y);
			assert(x<=y&&(x+y)%mod==b&&(ll)x*y%mod==c);
		}
	}
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

posted on 2018-10-23 11:07  autoint  阅读(310)  评论(0编辑  收藏  举报

导航