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 阅读(665) 评论(0) 编辑 收藏 举报