D1. Equalizing by Division (easy version)(有难度的思维题+逆向映射思维(2对1))

在这里插入图片描述
题意,给你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;
	
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值