POJ1186 方程的解数

人生第四道ACM题,学习到了开散列法。又写了两天时间,菜鸟就是菜鸟啊,什么都不会!

这已经是我目前做过最变态的一道了(前三道绝对没有这么复杂),写了87行啊有木有!英文题看不懂,所以老翻中文题做,但是中文题确实不好惹啊!!!不过所幸是一次提交就AC的,在这里给自己加油,鼓励自己一定要坚持下去!

这道题就是要求一个n元高次方程的解的个数,由于最多有6项,并且限制x的范围是1~150,所以总共的状态数有150^6 = 11390625000000,太多了。考虑把一半项移到右边,然后先对左边每一个Xi枚举求值并进行hash,全部求完后,再对右边进行枚举计算求值并检查该值是否在hash表中,如果有就加上左边得到这个值的状态数,没有就不管,然后就AC了,泪奔~~~

#include <iostream>

#include <cmath>

using namespace std;



const int STATUS = 3375010;

const int P = 611953;

int Slots[P], Nxt[STATUS], Key[STATUS], Val[STATUS], EN;

int M, k[6], p[6], s;



void hash(int key)

{

	int e, pos = (key % P + P) % P;

	e = Slots[pos];

	while (e != -1) {

		if (Key[e] == key) {

			Val[e]++;

			return;

		}

		e = Nxt[e];

	}

	Val[EN] = 1;

	Key[EN] = key;

	Nxt[EN] = Slots[pos];

	Slots[pos] = EN++;

}



void cal(int key)

{

	int e, pos = (key % P + P) % P;

	e = Slots[pos];

	while (e != -1) {

		if (Key[e] == key) {

			s += Val[e];

			return;

		}

		e = Nxt[e];

	}

}



bool check_k(int l, int h) 

{

	while (l <= h) {

		if (k[l++] != 0) 

			return false;

	}

	return true;

}



void generate(int mod, int l, int h, int sum)

{

	if (l > h) {

		if (mod == 1) hash(sum);

		else cal(-sum);

		return;

	}

	for (int x = 1; x <= M; ++x) {

		generate(mod, l + 1, h, sum + k[l]*(int)pow(double(x), p[l]));

	}

}



int main()

{

	int i, j, n;

	while (cin >> n >> M) {

		for (i = 0; i < n; i++) {

			cin >> k[i] >> p[i];

		}

		for (EN = i = 0; i < P; i++) {

			Slots[i] = -1;

		}

		if (check_k(0, n - 1)) {

			s = 1;

			for (i = 0; i < n; i++) {

				s *= M;

			}

			cout << s << endl;

			continue;

		}

		if (check_k(0, (n + 1) / 2 - 1)) hash(0);

		else generate(1, 0, (n + 1) / 2 - 1, 0);

		s = 0;

		if (check_k((n + 1) / 2, n - 1)) cal(0);

		else generate(2, (n + 1) / 2, n - 1, 0);

		cout << s << endl;

	}

	return 0;

}

你可能感兴趣的:(poj)