版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/V5ZSQ/article/details/83110107
Description
dreamoon初中时最喜欢在上数学课时睡觉了,每次睡觉时,都会被老师罚解很多道整系数一元二次多项式因式分解成两个整系数一元一次多项式相乘的题目,但
dreamoon很狡猾,写了一个能解因式分解的程序,故这个惩罚对
dreamoon没什么大不了的。
身为
dreamoon粉丝的你,也想效法
dreamoon(能够写出解因式分解的程序的部份),现在就来测试看看你写的程序是否正确吧
至于你应该要输出什么,详情请参考标准输出。
Input
输入的第一行有一个正整数
T,代表该笔测试资料含有多少组因式分解问题。
接下来有
T行,每个询问各占
1行,包含
3个整数
a,b,c,代表这个询问要你对
a⋅x2+b⋅x+c 做因式分解。
(1≤T≤50000,−109≤a,b,c≤109,a̸=0)
Output
对于每个因式分解问题,若有多种把
a⋅x2+b⋅x+c 分解成两个整系数一元一次多项式相乘,也就是形如
(s⋅x+t)×(u⋅x+v) 的方式,请找到使得
s⋅101000+t⋅10100+u⋅1010+v 最大的一组解,并输出四个整数
s,t,u,v 于一行。
若无法因式分解,则输仍然输出三个整数
a,b,c 于一行。
Sample Input
3
5 1 -4
5 1 4
5 0 0
Sample Output
5 -4 1 1
5 1 4
5 0 1 0
Solution
首先根据判别式判断
ax2+bx+c是否有解,如果有解,直接用求根公式
x1=2ab+b2−4ac
,x2=2ab−b2−4ac
做分解
ax2+bx+c=a(x+x1)(x+x2)
不妨记
x1=st,x2=uv,其中
s,u>0,gcd(s,t)=gcd(u,v)=1
显然若
su̸∣a则无整数解,否则化为
sua(sx+t)(ux+v),记
d=sua
若
s<u或
s=u,t<v,则交换
s,u以及
t,v,然后把
s,t变为原先的
∣d∣倍使得
s,t尽可能大,若
d为负则对
u,v取负即可
Code
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
int T,a,b,c;
ll u,v,s,t;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&a,&b,&c);
ll d=1ll*b*b-4ll*a*c,e=0;
if(d>=0)e=(ll)sqrt(d);
while(e*e<d)e++;
if(e*e!=d)printf("%d %d %d\n",a,b,c);
else
{
t=b+e,v=b-e,s=u=2*a;
ll g=gcd(abs(s),abs(t));
s/=g,t/=g;
g=gcd(abs(u),abs(v));
u/=g,v/=g;
if(s<0)s=-s,t=-t;
if(u<0)u=-u,v=-v;
if(a%((ll)s*u)!=0)printf("%d %d %d\n",a,b,c);
else
{
a/=s,a/=u;
if(s<u||s==u&&t<v)swap(s,u),swap(t,v);
s*=abs(a),t*=abs(a);
if(a<0)u=-u,v=-v;
printf("%lld %lld %lld %lld\n",s,t,u,v);
}
}
}
return 0;
}