POJ1186 方程的解数

与其说这题是双向广搜板子不如说是哈希表板子...

就像邻接表一样,哈希表挂的链就是邻接表的边

把计数器记在边权上偷懒

一开始看错了条件。。。

记得先模再加mod再模,防止负数 GG

有一个显然的事情是,模数大了空间会大,
模数小了 find 时间长


 代码:

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<cmath>
using namespace std;

const int MAXN = 10, mod = 333131;

struct EDGE{
    int nxt, to, val;
    EDGE(int NXT = 0, int TO = 0, int VAL = 0) {nxt = NXT; to = TO; val = VAL;}
}edge[3375005];
int n, m, mid, ans, totedge;
int k[MAXN], p[MAXN], x[MAXN];
int head[mod + 5];

inline int fastpow(int bot, int top) {
    register int ans = 1;
    while(top) {
        if(top & 1) ans *= bot;
        top >>= 1;
        bot *= bot;
    }
    return ans;
}
inline void add(int x, int y, int v) {
    edge[++totedge] = EDGE(head[x], y, v);
    head[x] = totedge;
    return;
}
inline void insrt(int res) {
    register int tmp = 0;
    tmp = (res % mod + mod) % mod;
    for(int i = head[tmp]; i; i = edge[i].nxt) if(edge[i].to == res) {
        ++edge[i].val;
        return;
    } 
    add(tmp, res, 1);
    return;
}
void lfs(int pos, int sig) {
    if(pos > mid) {
        insrt(sig);
        return;
    }
    int tmp = 0;
    for(int i = 1; i <= m; ++i) {
        x[pos] = i;
        tmp = k[pos] * fastpow(i, p[pos]);
        lfs(pos + 1, sig + tmp);
    }
    return;
}
void rfs(int pos, int sig) {
    if(pos <= mid) {
        register int tmp = ((-sig) % mod + mod) % mod;
        for(int i = head[tmp]; i; i = edge[i].nxt) if(edge[i].to == -sig) {
            ans += edge[i].val;
            return;
        }
        return;
    }
    int tmp = 0;
    for(int i = 1; i <= m; ++i) {
        x[pos] = i;
        tmp = k[pos] * fastpow(i, p[pos]);
        rfs(pos - 1, sig + tmp);
    }
    return;
}

int main() {
    scanf("%d%d", &n, &m);
    mid = (n >> 1);
    for(int i = 1; i <= n; ++i) 
        scanf("%d%d", &k[i], &p[i]);
    lfs(1, 0);
    rfs(n, 0);
    printf("%d\n", ans);
    return 0;
}
posted @ 2018-10-11 20:08  EvalonXing  阅读(182)  评论(0编辑  收藏  举报