与其说这题是双向广搜板子不如说是哈希表板子...
就像邻接表一样,哈希表挂的链就是邻接表的边
把计数器记在边权上偷懒
一开始看错了条件。。。
记得先模再加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;
}