Newcoder 110 C.因式分解(水~)

186 篇文章 0 订阅

Description

d r e a m o o n dreamoon dreamoon初中时最喜欢在上数学课时睡觉了,每次睡觉时,都会被老师罚解很多道整系数一元二次多项式因式分解成两个整系数一元一次多项式相乘的题目,但 d r e a m o o n dreamoon dreamoon很狡猾,写了一个能解因式分解的程序,故这个惩罚对 d r e a m o o n dreamoon dreamoon没什么大不了的。

身为 d r e a m o o n dreamoon dreamoon粉丝的你,也想效法 d r e a m o o n dreamoon dreamoon(能够写出解因式分解的程序的部份),现在就来测试看看你写的程序是否正确吧

至于你应该要输出什么,详情请参考标准输出。

Input

输入的第一行有一个正整数 T T T,代表该笔测试资料含有多少组因式分解问题。

接下来有 T T T行,每个询问各占 1 1 1行,包含 3 3 3个整数 a , b , c a, b, c a,b,c,代表这个询问要你对 a ⋅ x 2 + b ⋅ x + c a·x^2+ b·x +c ax2+bx+c 做因式分解。

( 1 ≤ T ≤ 50000 , − 1 0 9 ≤ a , b , c ≤ 1 0 9 , a ≠ 0 ) (1\le T\le 50000,-10^9\le a,b,c\le 10^9,a\neq 0) (1T50000,109a,b,c109,a̸=0)

Output

对于每个因式分解问题,若有多种把 a ⋅ x 2 + b ⋅ x + c a·x^2 + b·x +c ax2+bx+c 分解成两个整系数一元一次多项式相乘,也就是形如 ( s ⋅ x + t ) × ( u ⋅ x + v ) (s·x + t) \times (u·x + v) (sx+t)×(ux+v) 的方式,请找到使得 s ⋅ 1 0 1000 + t ⋅ 1 0 100 + u ⋅ 1 0 10 + v s·10^{1000}+ t·10^{100} + u·10^{10} + v s101000+t10100+u1010+v 最大的一组解,并输出四个整数 s , t , u , v s, t, u, v s,t,u,v 于一行。

若无法因式分解,则输仍然输出三个整数 a , b , c a, b, c 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

首先根据判别式判断 a x 2 + b x + c ax^2+bx+c ax2+bx+c是否有解,如果有解,直接用求根公式
x 1 = b + b 2 − 4 a c 2 a , x 2 = b − b 2 − 4 a c 2 a x_1=\frac{b+\sqrt{b^2-4ac}}{2a},x_2=\frac{b-\sqrt{b^2-4ac}}{2a} x1=2ab+b24ac ,x2=2abb24ac
做分解 a x 2 + b x + c = a ( x + x 1 ) ( x + x 2 ) ax^2+bx+c=a(x+x_1)(x+x_2) ax2+bx+c=a(x+x1)(x+x2)

不妨记 x 1 = t s , x 2 = v u x_1=\frac{t}{s},x_2=\frac{v}{u} x1=st,x2=uv,其中 s , u > 0 , g c d ( s , t ) = g c d ( u , v ) = 1 s,u>0,gcd(s,t)=gcd(u,v)=1 s,u>0,gcd(s,t)=gcd(u,v)=1

显然若 s u ̸ ∣ a su\not|a su̸a则无整数解,否则化为 a s u ( s x + t ) ( u x + v ) \frac{a}{su}(sx+t)(ux+v) sua(sx+t)(ux+v),记 d = a s u d=\frac{a}{su} d=sua

s &lt; u s&lt;u s<u s = u , t &lt; v s=u,t&lt;v s=u,t<v,则交换 s , u s,u s,u以及 t , v t,v t,v,然后把 s , t s,t s,t变为原先的 ∣ d ∣ |d| d倍使得 s , t s,t s,t尽可能大,若 d d d为负则对 u , v u,v 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值