因式分解

https://www.nowcoder.com/acm/contest/110/G

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

身为dreamoon粉丝的你,也想效法dreamoon(能够写出解因式分解的程序的部份),现在就来测试看看你写的程序是否正确吧〜
至于你应该要输出什么,详情请参考标准输出。

输入描述:

输入的第一行有一个正整数 T,代表该笔测试资料含有多少组因式分解问题。
接下来有 T 行,每个询问各占 1 行,包含 3 个整数 a, b, c,代表这个询问要你对 a·x2+ b·x +c 做因式分解。

输出描述:

对于每个因式分解问题,若有多种把a·x2 + b·x +c 分解成两个整系数一元一次多项式相乘,也就是形如(s·x + t) x (u·x + v) 的方式,请找到使得s·101000+ t·10100 + u·1010 + v 最大的一组解,并输出四个整数s, t, u, v 于一行。
若无法因式分解,则输仍然输出三个整数 a, b, c 于一行。

示例1

输入

3
5 1 -4
5 1 4
5 0 0

输出

5 -4 1 1
5 1 4
5 0 1 0

备注:

* 1 ≤ T ≤ 50000
* -109 ≤ a,b,c ≤ 109
* a ≠ 0
* 数据里所有的数都是整数

思路

一元二次整系数多项式因式整分解

根是不能决定方程具体的参数的,但是和参数是有关系的,也就是求根公式 b ± b 2 4 a c 2 a

所以有

b b 2 4 a c 2 a = t s b + b 2 4 a c 2 a = v u

这里 t , s u , v 可以调换(地位平等) 不妨先这样设

由于 a , b , c , t , s , u , v 全为整数

所以 δ 必须为有理数 又 a , b , c 全为整数 所以 b 2 4 a c 应为完全平方数 否则无solution

现在相当于我们确定了 t , s 的比例关系和 v , u 的比例关系

比较系数还可得

s u = a

既然确定了比例,我们可以设基本参数表示两个数,

但有一种比较方便的方法就是直接消去t,s (v,u)的gcd ,然后成比例扩大即可

所以只有当 a % s u == 0 时才有解 令a=a/su 则a为最后s t要扩大的倍数 因为在前面的越大越好

最后要确定题意中的最大的s,t,u,v

首先,我们让s,u为正数(显然,如果他们中的某个做了题目中最后的’s’位置,其为正是结果最大的情况) 对于s,若取相反数,则t,a也取相反数 (u同理)

然后,比较 s + t u + v 的大小

以确定哪一对是真正的“s,t”

最后要注意,扩大a(a/su)倍的时候,若a是负数,把-1分给u,v

代码示例

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define bit(a,b) ((a>>b)&1)
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const double pi=acos(-1.0);

ll a,b,c,s,t,u,v;

ll is_sqrt(ll x)
{
    ll t=sqrt(1.0*x)+0.5;
    return t*t==x ? t :-1 ;
}

ll gcd(ll a,ll b)
{
    if(b==0) return a;
    return gcd(b,a%b);
}


int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif
    ios::sync_with_stdio(false);
    int Case;
    cin>>Case;
    while(Case--)
    {
        cin>>a>>b>>c;
        ll del;
        if((del=is_sqrt(b*b-4*a*c))>=0){
            //debug<<del<<endl;
            s=u=2*a;   t=b-del;  v=b+del;
            ll g1=gcd(abs(t),abs(s));  ll g2=gcd(abs(v),abs(u));
            t/=g1; s/=g1;  v/=g2;  u/=g2;
            //debug<<s<<" "<<t<<" "<<u<<" "<<v<<endl;
            if(a%(s*u)==0){
                a/=(s*u);
                if(s<0) s=-s,t=-t,a=-a;
                if(u<0) u=-u,v=-v,a=-a;
                if(s*inf+t<u*inf+v){
                    swap(t,v);
                    swap(s,u);
                }
                if(a<0){a=-a;  u=-u;  v=-v;}
                t*=a;  s*=a;
                cout<<s<<" "<<t<<" "<<u<<" "<<v<<endl;
                continue;
            }
        }
        cout<<a<<" "<<b<<" "<<c<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/feynman1999/article/details/80373122
今日推荐