水题集合
来源:互联网 发布:淘宝买家秀 编辑:程序博客网 时间:2024/06/13 05:11
codeforces 558C
给N个数字,有两种操作,问最少多少次操作可以使这N个数字大小相同。
operator1 : 把数字乘以2
operator2 : 把数字除以2(int型除法)
cf上的标签是暴力,我不会。看了题解,这种思维我是真的没有,最近打算锻炼思维了,多刷有难度的水题!。
题解:
开两个数组,vis[maxn*2],cnt[maxn*2],vis[i]表示通过操作可以到达数字i的方式数量。cnt[i]表示所有可以到达数字i的数字到达i所需要的操作数的和。
在输入时,记录最大值。所有数字的最终值不会超过最大值。
然后枚举每个数字,通过位运算算出通过这个数字可以到达的每个状态,并且记录步数。
由于除法要取底。当x&1==1时,再把x向左移直到最大值。这样可以获取到多一些状态。
比如3可以变到8. 3>>1==1; 1<<3 = 8; 需要4步。
处理完以后,扫一遍,看那个数字可以从n个数字出发都达到它。然后去最小值即为答案。
#include<cstdio>#include<algorithm>#include<cstring>using namespace std;int num[100010*2];int vis[100010*2];int cnt[100010*2];int m;void solve(int a){ vis[a] ++; int s = 0; int tmp = a; while(tmp<=m) { tmp = tmp<<1; vis[tmp]++; s++; cnt[tmp] += s; } tmp = a; s = 0; while(tmp) { if(tmp&1 && tmp!=1) { tmp = tmp>>1; s++; vis[tmp] ++; cnt[tmp] +=s; int temp = tmp; int ss = s; while(temp<=m) { temp = temp<<1; ss++; vis[temp]++; cnt[temp]+=ss; } } else { tmp = tmp>>1; s++; vis[tmp] ++; cnt[tmp] +=s; } }}int main(){ int n; memset(cnt,0,sizeof(cnt)); memset(vis,0,sizeof(vis)); m = 0; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&num[i]); m = max(m,num[i]); } for(int i=0;i<n;i++) { solve(num[i]); } int res = 0x3f3f3f3f; for(int i=1;i<=200001;i++) { if(vis[i]==n) res = min(res,cnt[i]); } printf("%d\n",res); return 0;}
阅读全文
0 0
- 水题集合
- 集合题
- 字符串笔试题集合
- 集合排列组合题
- 集合相关编程题
- 集合的笔试题
- 求职笔试题集合
- JAVA笔试题集合
- 杂题集合
- 网络流题集合
- Java集合题
- 操作系统简单题集合
- 【算法题】集合
- [编程题] 字符集合
- 编程题【字符集合】
- [编程题] 集合
- [编程题] 集合
- 编程题集合
- Rxjava
- 子雨大数据之Spark入门教程
- JavaScript 风格指南(3)
- webpack学习
- Oracle 模糊查询的用法
- 水题集合
- 图片预加载之有序加载
- redis源码调试方法
- 喷水装置(一)
- 如何做SEO(关键词)
- ExtJS Grid获取选中值
- Codeforces-557D Vitaly and Cycle(二分图染色)
- 【NOIP2017】SummerTraining0707
- mysql中or和in的效率问题