poj 1186 哈希表构造

来源:互联网 发布:淘宝pv和uv下降的原因 编辑:程序博客网 时间:2024/06/13 02:38

思路:题目给定最多6元方程,每个解的范围给定了[1, 150],若n=6,直接枚举肯定超时 ,我们可以枚举出前三个解产生的值s1,存入表中。利用哈希表,由于x的取值范围是[1,150],三个解最多产生150*150*150种可能,这样就确定了哈希表的大小。再枚举后三个解产生的值s2,若s2 =s1,则说明这是一个解。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int MAX = 4000000;bool used[MAX] = {0};int ki[7], pi[7];struct Hash{    int val;    int count;};Hash HashTable[MAX];int n, m, ans, mid;int getpow(int x, int p) {    int tmp = 1;    while (p) {        if (p&1)            tmp *= x;        x *= x;        p >>= 1;    }    return tmp;}int searchHash(int s) {    int tmp;    tmp = s;    while (tmp < 0) tmp += MAX;    while (tmp >= MAX) tmp -= MAX;    while (used[tmp] && HashTable[tmp].val != s) {        tmp++;        if (tmp >= MAX)            tmp -= MAX;    }    return tmp;}void insert(int s) {    int pos = searchHash(s);    HashTable[pos].val = s;    used[pos] = 1;    HashTable[pos].count++;}void leftHalf(int k, int s) {    int i;    if (k == mid) {        insert(s);        return;    }    for (i = 1; i <= m; ++i) {        leftHalf(k+1,s+ ki[k]*getpow(i, pi[k]));    }}void rightHalf(int k, int s) {    int i, pos;    if (k == n) {        s = -s;        pos = searchHash(s);        if (HashTable[pos].val == s)            ans += HashTable[pos].count;        return;    }    for (i = 1; i <= m; ++i) {        rightHalf(k+1,s+ki[k]*getpow(i, pi[k]));    }}int main(){    scanf("%d", &n);    scanf("%d", &m);    int i;    ans = 0;    mid = n/2;    for (i = 0; i < n; ++i)        scanf("%d %d", &ki[i], &pi[i]);    leftHalf(0, 0);    rightHalf(mid, 0);    printf("%d\n", ans);    return 0;}


原创粉丝点击