cf題面函數
給n個數,每次能夠把其中一個數字位運算右移一位(即整除以二),問要至少操做幾回才能讓這n個數中有至少k個相等。spa
這題還有個數據範圍更小的簡單版本,n和k是50,\(a_i\)仍是2e5。.net
發現\(1\leqslant a_i\leqslant 2⋅10^5\),這些數字除以二隻會變小,換句話說,整個過程當中數字大小都不會超過\(2⋅10^5\),而後就能夠用相似桶排序的方法,把全部數字不停除以二,把獲得一個數字所用的步驟數(包括0步,即原數字)扔到相應的桶裏,以後統計每一個桶,有沒有k個數,若是有,就計算其中最小的k個步驟數之和,用於更新答案。(感受這段話還不如代碼好懂)code
這種思惟題,標籤都很差打,就模仿cf,給這題打個「暴力」的標籤算了排序
#include<vector> #include<cstdio> #include<algorithm> const int MAXN=2e5+5; int n,k,mxa; std::vector<int> t[MAXN];//t[i]表示達到i的操做次數 int main() { scanf("%d%d",&n,&k); while(n--) { int a; scanf("%d",&a); mxa=std::max(mxa,a); int cur=0; while(a) { t[a].push_back(cur); cur++; a>>=1; } t[0].push_back(cur); } int ans=0x7fffffff; for(int i=0;i<=mxa;i++) { if(t[i].size()<k) continue; std::sort(t[i].begin(),t[i].end()); int sum=0; for(int j=0;j<k;j++) sum+=t[i][j];//題解標程使用了accumulate函數 ans=std::min(ans,sum); } printf("%d\n",ans); return 0; }