题意
题解
朴素枚举方程的解进行判断,时间复杂度
O
(
M
N
)
O(M^N)
O(MN)。考虑折半枚举,将方程移项
∑
i
=
1
⌊
N
/
2
⌋
k
i
x
i
p
i
=
−
∑
i
=
⌊
N
/
2
⌋
+
1
N
k
i
x
i
p
i
\sum\limits_{i=1}^{\lfloor N/2\rfloor}k_ix_i^{p_i}=-\sum\limits_{i=\lfloor N/2\rfloor+1}^{N}k_ix_i^{p_i}
i=1∑⌊N/2⌋kixipi=−i=⌊N/2⌋+1∑Nkixipi 预处理左项的可能解并使之有序,枚举右项的可能解,同时二分求解满足方程的左项数量。总时间复杂度
O
(
M
N
/
2
log
(
M
N
/
2
)
)
O(M^{N/2}\log (M^{N/2}))
O(MN/2log(MN/2))。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 8, maxm = 155, maxt = maxm * maxm * maxm;
int N, M, na, nb, K[maxn], P[maxn], A[maxt], B[maxt];
int qpow(int x, int n)
{
int res = 1;
while (n)
{
if (n & 1)
res *= x;
x *= x, n >>= 1;
}
return res;
}
void dfs(int s, int t, int x, int &n, int *a)
{
if (s > t)
{
a[++n] = x;
return;
}
for (int i = 1; i <= M; ++i)
dfs(s + 1, t, x + K[s] * qpow(i, P[s]), n, a);
}
int main()
{
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; ++i)
scanf("%d%d", K + i, P + i);
int h = N >> 1;
dfs(1, h, 0, na, A), dfs(h + 1, N, 0, nb, B);
sort(A + 1, A + na + 1);
int res = 0;
for (int i = 1; i <= nb; ++i)
res += upper_bound(A + 1, A + na + 1, -B[i]) - lower_bound(A + 1, A + na + 1, -B[i]);
printf("%d\n", res);
return 0;
}