P5691 [NOI2001] Enumeration in half

Title

Portal P5691 [NOI2001] The number of solutions of the equation

answer

The solution of the naive enumeration equation is judged, and the time complexity is O (MN) O(M^N)O ( MN ). Consider the enumeration in half, and move the term
∑ i = 1 ⌊ N / 2 ⌋ kixipi = − ∑ i = ⌊ N / 2 ⌋ + 1 N kixipi \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=1N/2kixipi=i=N/2+1NkixipiThe possible solutions of the left term are preprocessed and ordered, the possible solutions of the right term are enumerated, and the number of left terms satisfying the equation is solved bisection. Total time complexity O (MN / 2 log ⁡ (MN / 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;
}

Guess you like

Origin blog.csdn.net/neweryyy/article/details/114340014