腾讯比赛的题目,有点难调,主要涉及重根处理的问题,首先如果常数项为零,就提取x,把0这个根加入队列,如果常数项不为零,就在常数项的因子里面枚举可能的根,如果最后取到的根的个数不足多项式一开始的最高次幂数,那么就说明有重根,将多项式求导,再用相同的方式求根,知道求导过后只剩常数项或者根的个数已经到达要求为止,如果最后根的个数还是不够,说明分解失败,输出-1,另外要注意孤弱一开始输入的多项式只有常数项,那么应该输出-1,一开始输入的多项式的最高次幂的系数如果不是1,那么分解也一定是不可能的,也应该在一开始输出-1,不需要再进行分解操作了。这道题的逻辑有点复杂,不需要深究,主要是学习这种因式分解的思路。在杭电的网站上测试的,居然0秒就过了,有点不可思议。
#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;
char buffer[200];
int case_count;
int a[6];
vector<int> root;
int cmp(const void *a, const void *b)
{
return *((int*)b) - *((int*)a);
}
void get_xishu()
{
int i, j, zhishu, xishu;
char *p, *start;
for(i=0; i<=5; i++)
a[i] = 0;
start = buffer;
while(1)
{
p = strstr(start, "x");
if(p == NULL)
break;
if(p[1] == '^')
sscanf(p+2, "%d", &zhishu);
else
zhishu = 1;
if( !(p[-1]>='0' && p[-1]<='9') )
{
if(p[-1] == '-')
xishu = -1;
else if(p[-1] == '+')
xishu = 1;
else if(p[-1] == '#')
xishu = 1;
}
else
{
for(i=-1; p[i]!='#'; i--)
if(p[i]=='+' || p[i]=='-')
break;
if(p[i] == '+')
sscanf(p+i+1, "%d", &xishu);
else if(p[i] == '-')
sscanf(p+i, "%d", &xishu);
else if(p[i]=='#')
sscanf(p+i+1, "%d", &xishu);
}
a[zhishu] += xishu;
start = p+1;
if(*start == '\0')
break;
}
//算常数项
for(i=0; i<strlen(buffer); i++)
{
if( (buffer[i]>='0'&&buffer[i]<='9') && !(buffer[i-1]>='0'&&buffer[i-1]<='9') && buffer[i-1]!='^')
{
for(j=i+1; j<=strlen(buffer); j++)
if( !(buffer[j]>='0'&&buffer[j]<='9') )
break;
if( buffer[j] != 'x' )
{
if(buffer[i-1] == '-')
sscanf(buffer+i-1, "%d", &xishu);
else
sscanf(buffer+i, "%d", &xishu);
a[0] += xishu;
}
}
}
}
void delete_x()
{
int i;
int temp[6];
for(i=0; i<=5; i++)
temp[i] = 0;
for(i=1; i<=5; i++)
{
if(a[i])
{
temp[i-1] = a[i];
}
}
memcpy(a, temp, 6*sizeof(int));
}
void qiudao()
{
int i;
int temp[6];
for(i=0; i<=5; i++)
temp[i] = 0;
for(i=1; i<=5; i++)
{
if(a[i])
{
temp[i-1] = i*a[i];
}
}
memcpy(a, temp, 6*sizeof(int));
}
bool is_root(long long x)
{
long long cifang;
long long sum;
int i;
cifang = 1;
sum = a[0];
for(i=1; i<=5; i++)
{
cifang *= x;
sum += a[i]*cifang;
}
if(sum == 0)
return true;
else
return false;
}
void func()
{
int max_zhishu;
int i, data;
get_xishu();
max_zhishu = 0;
for(i=5; i>=0; i--)
if(a[i])
{
max_zhishu = i;
break;
}
root.clear();
if(max_zhishu == 0)
{
if(a[0] == 0)
printf("Case #%d: -1\n", case_count);
else
printf("Case #%d: -1\n", case_count);
return;
}
if(a[max_zhishu] != 1)
goto end;
//先把0这个根全部提出来, 使得常数项不为0
while(1)
{
if(a[0] == 0)
{
root.push_back(0);
if(root.size() == max_zhishu)
goto end;
delete_x();
if(a[1]==0 && a[2]==0 && a[3]==0 && a[4]==0 && a[5]==0) //不可能再有根了
goto end;
}
else
{
//枚举所有常数项的因子,根只可能在这些因子里面
data = a[0]>0 ? a[0]:a[0]*(-1);
for(i=1; i<=data; i++)
{
if(data%i != 0)
continue;
if(is_root(i))
{
root.push_back(i);
if(root.size() == max_zhishu)
goto end;
}
if(is_root(i*(-1)))
{
root.push_back(i*(-1));
if(root.size() == max_zhishu)
goto end;
}
}
qiudao();
if(a[1]==0 && a[2]==0 && a[3]==0 && a[4]==0 && a[5]==0) //不可能再有根了
goto end;
}
}
end:
if(root.size() == max_zhishu)
{
printf("Case #%d: ", case_count);
int all_root[6];
for(i=0; i<root.size(); i++)
all_root[i] = root[i];
qsort(all_root, root.size(), sizeof(int), cmp);
for(i=0; i<root.size(); i++)
{
data = all_root[i]*(-1);
if(data > 0)
printf("(x+%d)", data);
else if(data == 0)
printf("x");
else
printf("(x%d)", data);
}
printf("\n");
}
else
{
printf("Case #%d: -1\n", case_count);
}
}
int main(void)
{
int n;
//freopen("input.dat", "r", stdin);
gets(buffer);
sscanf(buffer, "%d", &n);
case_count = 0;
while(n--)
{
case_count++;
gets(buffer+1);
buffer[0] = '#';
func();
}
return 0;
}