题意,给你n个数字,然后你可以对其中的任意数字进行任意多次/2操作(向下取整);使得相同个数为k个的最小总的操作次数输多少?
看了大佬的代码;这个思维有点厉害哦;
思路:
把每个数/2直到为0;把结果给Ve[下标]中的下标;然后放入这个数变成下标值的次数;
这个我感觉很巧妙;因为感觉有点像映射;这样一个Ve[index].size就表示原数组中有多少个数经过/2能变成index;然后每次这个向量里面存的就是每个数的变成index的操作次数;
所以我之后就只需要枚举然后比较size和k的大小,然后sort排序求最小操作次数就OK了;
这个想法太NB了;orz。
这里就是定的未知的相同的数字(求出来的),去枚举的最小操作次数;感觉以前我好想遇见过似的,(@ 。@)
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,k;
vector<int> Ve[200050];
int a[60];
int main(){
scanf("%d %d",&n,&k);
int cnt=0;
for(int i=0;i<n;i++){
scanf("%d",a+i);
cnt=0;
while(a[i]){//存数,这里很巧妙的把 数字和个数和操作次数给对应起来了
Ve[a[i]].push_back(cnt++);
a[i]/=2;
}
}
int t,ans=0x3f3f3f3f;
for(int i=0;i<200050;i++){//因为ai最大才2e5所以可以这样枚举
t=0;
if(Ve[i].size()<k)continue;//如果i这个数不满足k个
sort(Ve[i].begin(),Ve[i].end());//因为我要求最少操作次数
for(int j=0;j<k;j++){//求前k个
t+=Ve[i][j];
}
ans=min(ans,t);///每次更新最小值
}
printf("%d\n",ans);
return 0;
}