洛谷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;
}
posted @ 2020-09-18 10:47  quanjun  阅读(148)  评论(0编辑  收藏  举报