Codeforces Round 1108 (Div. 2) D
Problem Summary
You are given an array of length with . Before the game starts, Alice may increment any single element any number of times, each increment counted as one step. Then Alice and Bob alternate turns, with Bob moving first. On Bob’s turn he picks two positions and swaps them (possibly the same position). On Alice’s turn: if is even, she picks the largest such that for all , then divides every () by — this counts as one step; otherwise she decreases by , again one step. When any value becomes zero it is removed from the array. Bob wants to maximise Alice’s total number of steps, Alice wants to minimise it. Output the minimum number of steps Alice performs.
Approach
First consider the version without the pre-game
+1operations. If there is any odd number, Alice cannot perform the global halving move, so the answer is , where denotes the bit-length of . If every number is even, Alice can keep halving globally until some value becomes odd, and after that the cost above still applies.This suggests fixing the number of global halvings we perform as , then computing the minimum number of
+1operations required to make every a multiple of . A naive choice is , but that isn’t always optimal — sometimes a few extra+1s can eliminate more -bits from the binary representation. So we need to search a small window around .How wide should the window be? Notice that is bounded by for . That means increasing by more than is never worthwhile — the extra
+1s would already exceed the entire remaining cost. So for every element we only need to try the values immediately above , keep those divisible by , and pick the minimum. Total complexity: .
Code
#include<bits/stdc++.h>using namespace std;
#define endl '\n'#define fi first#define se second#define ll long long#define lowbit(x) (x&(-x))const int mod=998244353;const double eps=1e-12;const int inf=0x3f3f3f3f;const ll INF=0x3f3f3f3f3f3f3f3f;#define popcnt __builtin_popcountint dcmp(double x){if(fabs(x)<eps)return 0;return x>0?1:-1;}
#define int ll
// mt19937 rnd(random_device{}());// uniform_int_distribution<int>dist(0,1000000);
int a[100005];int b[100005];int jie[21];
int len(int x){ int cnt=0; while(x) { cnt++; x>>=1; } return cnt;}
void solve(){ int n; cin>>n; int ans=inf; for(int i=1;i<=n;i++) { cin>>a[i]; } for(int j=0;j<=20;j++) { int res=j; for(int i=1;i<=n;i++) { int tmp=inf; for(int k=a[i];k<=a[i]+33;k++) { if(k%jie[j]==0) { b[i]=k/jie[j]; tmp=min(tmp,k-a[i]+popcnt(b[i])+len(b[i])-1); } } b[i]=a[i]+jie[j]-a[i]%jie[j]; tmp=min(tmp,b[i]-a[i]+popcnt(b[i]/jie[j])+len(b[i]/jie[j])-1); res+=tmp; } ans=min(ans,res); } cout<<ans<<'\n';}
/* 1101000 10 100 1*/
#undef int
int main(){ ios::sync_with_stdio(false);cin.tie(nullptr); // cout<<fixed<<setprecision(10);
jie[0]=1; for(int i=1;i<=20;i++) { jie[i]=jie[i-1]*2; }
int _;cin>>_;while(_--) { solve(); } return 0;}