poj 1186:方程的解数

题目描述如下:

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。

方程的整数解的个数小于2 31
★本题中,指数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;
} 





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值