洛谷P5691 [NOI2001]方程的解数 题解 折半搜索
题目链接:https://www.luogu.com.cn/problem/P5691
解题思路:
因为暴搜的时间复杂度为 \(O(150^6)\),所以采用折半搜索(meet-in-middle search)。
我这里用 map 记录 hash,所以总的时间复杂度为 \(O(12 \cdot 150^3)\)。
示例代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 7;
#define INF (1LL<<31)-1
int n;
long long m, k[maxn], p[maxn], a[maxn], ans;
long long Pow(long long a, long long b) {
if (b == 1) return a;
long long t = Pow(a, b/2);
t *= t;
if (b % 2) t *= a;
return t;
}
map<long long, int> mp;
void dfs1(int id, long long tmp, long long abstmp) {
if (id > n/2) {
mp[tmp] ++;
return;
}
for (long long i = 1; i <= m; i ++) {
long long t = k[id] * Pow(i, p[id]);
if (abstmp + abs(t) > INF) break;
dfs1(id+1, tmp+t, abstmp+abs(t));
}
}
void dfs2(int id, long long tmp, long long abstmp) {
if (id > n) {
ans += mp[-tmp];
return;
}
for (long long i = 1; i <= m; i ++) {
long long t = k[id] * Pow(i, p[id]);
if (abstmp + abs(t) > INF) break;
dfs2(id+1, tmp+t, abstmp+abs(t));
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i ++) cin >> k[i] >> p[i];
dfs1(1, 0, 0);
dfs2(n/2+1, 0, 0);
cout << ans << endl;
return 0;
}