您的位置:首页 > 其它

poj 1186:方程的解数

2014-09-25 00:15 204 查看
题目描述如下:

1186:方程的解数

总时间限制: 15000ms 内存限制: 128000kB 描述已知一个n元高次方程:



其中:x1, x2,...,xn是未知数,k1,k2,...,kn是系数,p1,p2,...pn是指数。且方程中的所有数均为整数。

假设未知数1 <= xi <= M, i=1,,,n,求这个方程的整数解的个数。

1 <= n <= 6;1 <= M <= 150。



方程的整数解的个数小于231。

★本题中,指数Pi(i=1,2,...,n)均为正整数。输入第1行包含一个整数n。第2行包含一个整数M。第3行到第n+2行,每行包含两个整数,分别表示ki和pi。两个整数之间用一个空格隔开。第3行的数据对应i=1,第n+2行的数据对应i=n。输出仅一行,包含一个整数,表示方程的整数解的个数。样例输入
3
150
1  2
-1  2
1  2

样例输出
178


一看到题目时,除了暴力,一时也没思路,于是在网上查看了几个人的博客,总结了一下思路。

例如,有n=6,即有6个xi项需要计算,这时,可先计算前三个项的和S,再计算后三个项若后三项的和等于-S,则找到一个解。

程序里将每一个S的和保存在map容器里,这样计算后三项时查找-S时,可以更快,因为map里的key与value是通过hash匹配的。

程序里,用到了递归,例如findLeft函数,它计算前n/2项的和S,并把它保存在countMap容器里。findRight函数计算后n/2项的和,转换成-S,并查看在countMap里,是否有相等项,注意,必须使用count()函数来判断S是否在Map容器里,而不能直接使用countMap[S],因为这样会在容器中增加新项,从而导致内存占用过大。

程序的代码如下:

#include <iostream>
#include <map>
using namespace std;
int countN,n,m,mid,k[6],p[6];
map<int,int> countMap;

// 搜索前一半
void findLeft(int xi, int temps){
if (mid == xi){
++countMap[temps];
return;
}

int t;
for (int i = 1; i <= m; ++i){
t = k[xi]; // xi的系数
if (t != 0 && i != 1) // 系数为0或xi=1时,则不用计算次数
for (int j = 0; j < p[xi]; ++j) // 计算xi的次方
t *= i;
findLeft(xi + 1, temps + t); // 计算x[i+1],即下一个项
}
}

// 搜索另一半,并将结果返回至列表
void findRight(int xi, int temps){
if (xi == n){
temps = -temps;
if (countMap.count(temps))
countN += countMap[temps];
return;
}

int t;
for (int i = 1; i <= m; ++i){
t = k[xi]; // xi的系数
if (t != 0 && i != 1) // 系数为0或xi=1时,则不用计算次数
for (int j = 0; j < p[xi]; ++j) // 计算xi的次方
t *= i;
findRight(xi + 1, temps + t); // 计算x[i+1],即下一个项
}
}

int main()
{
cin >> n >> m;
mid = n / 2;
for (int i = 0; i < n; ++i)
cin >> k[i] >> p[i];
findLeft(0,0);
findRight(mid, 0);
cout << countN <<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj 递归