CF #312.div2 -Amr and Chemistry-暴力+位运算
2015-08-18 11:16
375 查看
题意:给出n个数,让你通过下面两种操作,把它们转换为同一个数。求最少的操作数。
1.ai = ai*2
2.ai = ai/2,向下取整
没什么思路,后来看到别人是这样暴力过的:
用左移右移来代替乘除2
vis[i] 表示 i 这个数可以由几个数转化而来
cnt[i] 表示题目给出的 n 个数全部转化为 i 需要的操作数。
设输入n个数最大为maxx
对于最后转化的结果的范围 ,应该是1 到 2*maxx (0或大于maxx*2都不是最优的,)
所以vis和cnt数组都开[2*maxx]
左移操作:
对于一个数,不断左移,每次左移,把等到的数组x,标记vis[X]++,cnt[x]+=step ,step为第一次到当前的步数,直到超maxx
右移操作:
(重复下面两操作直到该数为0)
若一个数最低位为1,先右移一步,再复制该数,再不断左移,上限为maxx; (因为不先右移一步得到的数就和左移操作中重复了)
若一个数最低位为0,右移一步,每一步更新得到的数的个数和步数 ()
这样我们就把每个数 的所有 移动情况都处理出来了,并且是最少的步数。
然而遍历数组 ,找vis【I】==n, 且cnt[i]最小的就是答案
1.ai = ai*2
2.ai = ai/2,向下取整
没什么思路,后来看到别人是这样暴力过的:
用左移右移来代替乘除2
vis[i] 表示 i 这个数可以由几个数转化而来
cnt[i] 表示题目给出的 n 个数全部转化为 i 需要的操作数。
设输入n个数最大为maxx
对于最后转化的结果的范围 ,应该是1 到 2*maxx (0或大于maxx*2都不是最优的,)
所以vis和cnt数组都开[2*maxx]
左移操作:
对于一个数,不断左移,每次左移,把等到的数组x,标记vis[X]++,cnt[x]+=step ,step为第一次到当前的步数,直到超maxx
右移操作:
(重复下面两操作直到该数为0)
若一个数最低位为1,先右移一步,再复制该数,再不断左移,上限为maxx; (因为不先右移一步得到的数就和左移操作中重复了)
若一个数最低位为0,右移一步,每一步更新得到的数的个数和步数 ()
这样我们就把每个数 的所有 移动情况都处理出来了,并且是最少的步数。
然而遍历数组 ,找vis【I】==n, 且cnt[i]最小的就是答案
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> #include<bitset> #include <map> #include <set> #include <vector> using namespace std; #define INF 0x7f7f7f7f const __int64 maxn = 100060; int max(int a,int b) {return a>b?a:b;} int min(int a,int b) {return a<b?a:b;} int vis[2*maxn ]; int cnt[maxn*2]; int maxx=0; int slove(int x) { vis[x]++; int temp1=x; int temp2=x; int step1=0; int step2=0; while(temp1<=maxx) { temp1<<=1; step1++; vis[temp1]++; cnt[temp1]+=step1; } while(temp2) { if (temp2&1 && temp2!=1) //最低位为1 { temp2>>=1; step2++; vis[temp2]++; cnt[temp2]+=step2; int temp3=temp2; int step3=step2; while (temp3<=maxx) { temp3<<=1; step3++; vis[temp3]++; cnt[temp3]+=step3; } } else { temp2>>=1; step2++; vis[temp2]++; cnt[temp2]+=step2; } } return 0; } int a[maxn]; int main() { int n,i; scanf("%d",&n); for (i=1;i<=n;i++) { scanf("%d",&a[i]); maxx=max(maxx,a[i]); } for (i=1;i<=n;i++) slove(a[i]); int ans=1<<25; for (i=1;i<=2*maxx;i++) { if (vis[i]==n) ans=min(ans,cnt[i]); } printf("%d\n",ans); return 0; }
相关文章推荐
- 从CPU核心架构看2016年移动设备趋势,A72到底能带来什么?
- C++零基础教程游戏开发入门
- 常用注释总结
- Maven实践一:HelloWord项目构建部署
- 给ubuntu中的软件设置desktop快捷方式(以android studio为例)
- uefi 里面如何抓到一个变量
- 妇仇者联盟--寡姐时代
- Go语言net/http 解读.
- Cocos2d-x学习笔记(十三)—— 数据解析(json/xml)
- java接口和抽象类
- hdoj.2256 Problem of Precision【矩阵快速幂】 2015/08/18
- hdoj 3342 Legal or Not 【拓朴排序】
- vijos - P1447开关灯泡 (大数模板 + 找规律 + 完全数 + python)
- 19.6.1 Partitioning Keys, Primary Keys, and Unique Keys 分区键,主键,和唯一健
- Hdu oj 2066 一个人的旅行
- #程序猿之路需要自己来铺垫#
- 第六章、输入输出系统
- JQuery实现数字滚动增加的效果
- Component Object Model
- Build your first Django site - QA