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;
}
posted on 2011-07-20 15:37 ComeOn4MyDream 阅读(676) 评论(0) 收藏 举报
浙公网安备 33010602011771号