实际上就是另f(Dep,Sum)表示当前已经算到了第i位,然后当前得到的值是Sum的所有的方案数量,那么可以发现
∑xDep−1=1Mf(Dep−1,Sum−kDep×xPDepDep)=f(Dep,Sum)=∑xDep+1=1Mf(Dep+1,Sum+kDep+1×xPDep+1Dep+1)
因为
Sum有可能是一个负的数字,而且Sum可能很大,hash搞一下就好了,然后双向DFS
#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 15000000;
const int MAX_NUM = 12345678;
struct node{int val, count;}hashset[MAXN+10];
int _k[8], P[8], M, n, e1, e2;
int h(int k){
int x = ((k % MAX_NUM) + MAX_NUM) % MAX_NUM;
while(hashset[x].count > 0 && hashset[x].val != k)
x = (x + 1) % MAX_NUM;
return x;
}
int Pow(int u, int k){
int ret = 1, tmp = u;
while(k){
if(k & 1)
ret *= tmp;
tmp *= tmp;
k >>= 1;
}
return ret;
}
void dfs1(int i, int sum){
if(i == e1){
int hid = h(sum);
hashset[hid].val = sum;
hashset[hid].count++;
return ;
}
for(int u=1;u<=M;u++)
dfs1(i+1, sum+_k[i+1] * Pow(u, P[i+1]));
}
int ans;
void dfs2(int i, int sum){
if(i == e2){
int hid = h(sum);
ans += hashset[hid].count;
return ;
}
for(int u=1; u<=M;u++)
dfs2(i-1, sum-_k[i-1] * Pow(u, P[i-1]));
}
int main(){
scanf("%d%d", &n, &M);
e1 = n/2, e2 = n/2+1;
for(int i=1;i<=n;i++)
scanf("%d%d", &_k[i], &P[i]);
dfs1(0, 0);
dfs2(n+1, 0);
printf("%d\n", ans);
return 0;
}