用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字
云代码 - c代码库

2013腾讯马拉松初赛 ACM 威威猫系列故事——因式分解

2013-03-28 作者: 小蜜锋举报

[c]代码库

/*

2013腾讯马拉松初赛第3场

1002 威威猫系列故事——因式分解
 
Time Limit: 0.2 Seconds   Memory Limit: 65536K
 
“春天来了,万物复苏,大地一片生机盎然,又到了动物们求偶的季节...”
周末的威威猫虽然眼睛盯着电视屏幕,但是思绪却停留在自己喜欢的数学问题上。
有人说孤独是可耻的,但是单身一人的威威猫并不孤独,随着对数学的深入学习,威威猫甚至很庆幸自己没有陷入儿女情长,因为他有喜爱的数学相伴,最近,他就在潜心研究因式分解问题。
在我们学习数学的过程中,经常需要把一个多项式进行因式分解,也就是把它写成乘积的形式,比如多项式x^2+3x+2分解因式的结果就是(x+1)(x+2)。这个因式一眼就能看出来,但是当x的指数更高时,就不太容易分解了。
现在,威威猫就是在研究如何编写程序来实现对多项式的因式分解。
Input
输入第一行是一个整数T(T<=50),表示测试数据的组数;
接下来是T行字符串表示T个测试用例,每行1个数学多项式,多项式长度不会超过100个字符,每个多项式表示形式如下:	A[1]x^P[1]+A[2]x^P[2]+...+A[m]x^P[m]
其中0<=P[i]<=5,A[i]表示x^P[i]的系数,A[i]=0时直接简写为0,A[i]=1和-1时分别简写为x^P[i]与-x^P[i],P[i]=0和1时分别简写为A[i]与A[i]x,且同一指数r的对应项系数之和的绝对值不超过1000, 每行中没有多余空格,具体格式可参考Sample Input。
Output
对于每组测试数据,首先输出Case #X: ,X代表多项式编号,从1开始计数,然后输出因式分解的结果,分解结果的表示形式规定如下:
(x+B[1])(x+B[2])...(x+B[m])
其中,B[1]<=B[2]<=...<=B[m],若B[i]=0则不加括号直接简写为x,如果无法表现成上述格式,则输出"-1"。
具体可参考Sample Output。
Sample Input
4
x
x+1
-2x^2+x^2+x^3
2x+2

Sample Output
Case #1: x
Case #2: (x+1)
Case #3: (x-1)xx
Case #4: -1
 
*/

/*
解题报告:

这题的话初看很难,一些头续也没有。
仔细研究会发现,p[i]比较小,最多是5,也就是说,分解出来的因式最多5个。
每一个因子是形如(x+b[i])也就是说确定b[i]就可以了。
题目中说了每一项系数绝对值不超过1000,我们考虑最后一项常数项
常数项是由b[1]*b[2]*b[3]*b[4]*...*b[5]

也就是说这些b[i]是常数项的因子,而且乘起来要等于常数项。

常数项不大,我们可以枚举常数项的因子。

然后去验证。

之儿有一个小问题就是,如果常数项为0怎么办,这种情况下的话,也就是说大家可以提出一个x来,如果还是0,就再提x。
对最后常数项不为0的进行分解就行了。
*/


#include<stdio.h>
#include<string.h>
#include<algorithm>

using namespace std ;
const int MAX = 110;
const int INF = 100000000;
char s[MAX];
int c[6];
struct BigNum {
    int dig[6];
    int len;
    void clr() {
        len = 1;
        memset(dig, 0, sizeof(dig));
    }
};

bool dig(char x) {
    return x >= '0' && x <= '9';
}
BigNum f;
BigNum Div(BigNum a, int b) {
    int i;
    int t;
    BigNum ret;
    ret.clr();
    for(i = a.len - 1; i >= 1; i--) {
        t = a.dig[i];
        ret.dig[i - 1] += t;
        a.dig[i] = 0;
        a.dig[i - 1] -= b * t;
    }
    ret.len = -1;
    if(a.dig[0] != 0)return ret;

    for(i = 5; i >= 0 && ret.dig[i] == 0; i--);

    ret.len = i + 1;
    return ret;
}
int calc() {
    int i;
    if(f.dig[0] == 0) {
        for(i = 0; i + 1 < f.len; i++) {
            f.dig[i] = f.dig[i + 1];
        }
        f.len--;
        return 0;
    }
    for(i = -1000; i <= 1000; i++) {
        if(i == 0 && f.dig[0] != 0)continue;
        else if(i != 0 && f.dig[0] % i != 0)continue;

        BigNum tmp = Div(f, i);
        if(tmp.len == -1)continue;
        f = tmp;
        return i;
    }
    return INF;
}
int main () {
    int T, CS = 1;
    int len;
    int tmp, p;
    int i;
    scanf("%d", &T);
    while (T--) {
        scanf("%s", s);
        memset(c, 0, sizeof(c));
        len = strlen(s);
        int left, right;
        for(i = 0; i < len; i++) {
            if(s[i] == 'x') {
                //计算有边
                if(s[i + 1] == '^') {
                    right = i + 2;
                    p = s[right] - '0'; //最多是5,取1为就行了
                } else {
                    right = i;
                    p = 1;
                }

                int ten = 1;

                left = i - 1;
                tmp = 0;
                while(left >= 0 && dig(s[left])) {
                    tmp += (s[left] - '0') * ten;
                    ten *= 10;
                    left--;
                }

                if(tmp == 0)tmp++;

                if(left >= 0 && s[left] == '-') {
                    tmp = -tmp;
                    left--;
                }

                c[p] += tmp;

                for(left++; left <= right; left++) {
                    s[left] = 1;
                }
            }
        }
        //puts("zz");
        for(i = 0; i < len; i++) { //求剩下的常数
            if(s[i] == '-' || dig(s[i])) {
                int sign = 1;
                tmp = 0;
                if(s[i] == '-') {
                    sign = -1;
                    i++;
                }
                while(i < len && dig(s[i])) {
                    tmp = tmp * 10 + s[i] - '0';
                    i++;
                }
                i--;
                c[0] += tmp * sign;
            }
        }
        int maxc = 5;
        while(maxc >= 0 && c[maxc] == 0) {
            maxc--;
        }
        printf("Case #%d: ", CS++);
        if(maxc <= 0) {
            puts("-1");
            continue;
        } else if(c[maxc] != 1) {
            puts("-1");
            continue;
        }
        //puts("");for(i=0;i<=maxc;i++)printf("x[%d]=%d\n",i,c[i]);
        int ans[6];

        f.clr();
        memcpy(f.dig, c, sizeof(c));
        f.len = maxc + 1;
        for(i = 0; i < maxc; i++) {
            ans[i] = calc();
            if(ans[i] == INF)break;
        }
        if(i < maxc) {
            puts("-1");
        } else {
            sort(ans, ans + maxc);
            for(i = 0; i < maxc; i++) {
                if(ans[i] == 0)putchar('x');
                else if(ans[i] < 0)printf("(x%d)", ans[i]);
                else printf("(x+%d)", ans[i]);
            }
            puts("");
        }
    }
    return 0 ;
}


网友评论    (发表评论)

共2 条评论 1/1页

发表评论:

评论须知:

  • 1、评论每次加2分,每天上限为30;
  • 2、请文明用语,共同创建干净的技术交流环境;
  • 3、若被发现提交非法信息,评论将会被删除,并且给予扣分处理,严重者给予封号处理;
  • 4、请勿发布广告信息或其他无关评论,否则将会删除评论并扣分,严重者给予封号处理。


扫码下载

加载中,请稍后...

输入口令后可复制整站源码

加载中,请稍后...