DP
dp[bit][j]填完了bit位之后,产生进位的状态是j,所需的最小花费。
若j以二进制(0010010..)的第i位表示第i个数是否发生进位,则j的状态有1<<n个;
假设结束时所有数均为X,考虑每个数第bit位是否有进位,即在模 1 << (bit + 1) 下 a[i] >= X是否满足。
由此可知,将a[i]按照a[i] mod (1 << (bit + 1)) 排序后产生进位的a[i]是连续的。j的状态降为n个。
然后进行DP即可。
#include<bits/stdc++.h>
using namespace std;
#define CLR(x, y) memset(x, y, sizeof(x))
#define MIN(a, b) a = min(a, b)
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
typedef long long LL;
int n;
LL a[N], b[N];
int dp[2][N];
void Sort(LL bit)
{
int n1 = 0;
for(int i = 0; i < n; i++)
b[i] = a[i];
for(int i = 0; i < n; i++)
{
if(b[i] & bit)
a[n1++] = b[i];
}
for(int i = 0; i < n; i++)
{
if(!(b[i] & bit))
a[n1++] = b[i];
}
}
int main ()
{
LL mx = 0;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%lld", &a[i]);
mx = max(mx, a[i]);
}
CLR(dp[0], INF);
dp[0][0] = 0;
for(int i = 0; ; i++)
{
bool f = i & 1;
int cntl = 0, cntr = 0;
CLR(dp[f ^ 1], INF);
for(int j = 0; j < n; j++)
{
if(a[j] & (1LL << i))
cntr++;
}
for(int j = 0; j <= n; j++)
{
if(dp[f][j] != INF)
{
MIN(dp[f ^ 1][j + cntr], dp[f][j] + j - cntl + cntr);
MIN(dp[f ^ 1][cntl], dp[f][j] + cntl + (n - j - cntr));
}
if(a[j] & (1LL << i))
{
cntl++;
cntr--;
}
}
if(f && (1LL << i) > mx)
break;
Sort(1LL << i);
}
printf("%d\n", dp[0][0]);
return 0;
}