求证明复杂度
查看原帖
求证明复杂度
413065
xiezheyuan楼主2024/12/26 19:31

这是我的实现,我猜测时间复杂度为 O(m2m)O(m2^m),但实际表现类似 O(m22m)O(m^22^m)(在 libreoj 开 Ofast 仍然无法通过,在 lg 因为时间限制为 3s 可以通过),求这份代码的时间复杂度到底是什么,是假了还是就是单纯的写丑了?

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5, M = 25, M_ = (1 << 23) + 1;
int n, m, p, a[N], g[M][M], f[M_], h[M][M_ >> 1], highbit[M_], popcount[M_];

int rev(int x, int i){
    return x >= i ? x + 1 : x;
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin >> n >> m >> p;
    for(int i=1;i<=n;i++){
        cin >> a[i];
        g[a[i - 1]][a[i]]++;
    }
    for(int j=1;j<(1 << m);j++){
        popcount[j] = __builtin_popcount(j);
        highbit[j] = 32 - __builtin_clz(j);
    }
    for(int i=1;i<=m;i++){
        for(int t=1;t<m;t++) h[i][0] += p * g[rev(t, i)][i] - g[i][rev(t, i)];
        for(int siz=0;siz<(m - 1);siz++){
            for(int s=0;s<(1 << (m - 1));s++){
                if(popcount[s] != siz) continue;
                for(int t=highbit[s]+1;t<m;t++){
                    int tmp = h[i][s];
                    tmp += p * g[i][rev(t, i)] + g[rev(t, i)][i];
                    tmp -= p * g[rev(t, i)][i] - g[i][rev(t, i)];
                    h[i][s | (1 << (t - 1))] = tmp;
                }
            }
        }
    }
    for(int i=1;i<=m;i++){
        for(int j=1;j<(1 << m);j++){
            if(popcount[j] != i) continue;
            f[j] = INT_MAX;
            for(int k=1;k<=m;k++){
                if(!(j & (1 << (k - 1)))) continue;
                int status = (j & ((1 << (k - 1)) - 1));
                int remain = j ^ (1 << (k - 1));
                status |= (remain ^ status) >> 1;
                f[j] = min(f[j], f[remain] + h[k][status] * i);
            }
        }
    }
    cout << f[(1 << m) - 1] << '\n';
    return 0;
}

// Written by xiezheyuan
2024/12/26 19:31
加载中...