这是我的实现,我猜测时间复杂度为 O(m2m),但实际表现类似 O(m22m)(在 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