AOJ 794.西瓜理发记(二)

Time Limit: 1000 ms   Case Time Limit: 1000 ms   Memory Limit: 64 MB
Total Submission: 151   Submission Accepted: 28
Description
剃完光头后,西瓜表示非常开心,于是直接骑上自行车去往勺林寺。
等骑到勺林寺的时候,头发已经都长出来了,于是西瓜决定在附近的理发店再剃一次。
然而这里的理发店老板WzyJerry表示正在做ACM练习,没空给他理发。
西瓜决定帮助老板AK。
题目是这样的:
你现在有一个培养盒,盒中没有细菌
每天早上,你可以向盒中放入一个细菌
每天晚上,一个细菌会分裂成两个。
求如果你想在将来的某天使盒中恰好有n个细菌,你最少要向盒中放入几个细菌

 

Input
输入数据包含多组
每组一个整数n(1≤n ≤10^9)

 

Output
每组数据输出一个整数x,表示最少需要放入的细菌个数

 

Sample Input
OriginalTransformed
5
1

 

Sample Output
OriginalTransformed
2
1
 
提供两种思路
  1. 模拟
  2. 位运算(2进制)

模拟(被注释部分)

使用DFS来模拟操作。

从1个细菌开始

早上分别选择放入细菌和不放入细菌,而后与要求匹配,查看是否符合

晚上在两种情况下分别将细菌乘2,继续DFS

这种方法比较直观,代码也很简单,但是效率非常低,需要将树的所有分支都遍历至n,而树有2n个叶,也即时间效率为O(2n)

 

位运算(2进制)

由模拟算法,我们发现时间效率与2n有关系,因此,可以比较容易想到2进制的算法。

早上是否放入,可看做最低位是否为1;晚上乘2可看作左移一位(<<1)。

由于得到n个细菌是唯一的,所以n(2)中的1的个数为最优解,也是唯一解。

因此,只需判断n(2)中的1的个数即可。

该算法的效率只和n的二进制位数有关时间效率为O(n),并且采用二进制运算,每次运算量也非常小。

 

 

 

 1 #include <cstdio>
 2 #include <string>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <memory>
 6 #include <stack>
 7 #include <queue>
 8 #include <set>
 9 #include <algorithm>
10 #include <map>
11 #include <vector>
12 using namespace std;
13  
14 #define debug 0
15  
16 /*
17 By:OhYee
18 Github:OhYee
19 Email:oyohyee@oyohyee.com
20 Blog:http://www.cnblogs.com/ohyee/
21 
22 かしこいかわいい?
23 エリーチカ!
24 要写出来Хорошо的代码哦~
25 */
26 
27 int N;
28 /*
29  
30 int ans=999999;
31 void DFS(int n,int cnt){
32     //printf("%d %d\n",n,cnt);
33     if(n==N)
34         ans=min(cnt,ans);
35     if(n+1==N)
36         ans=min(cnt+1,ans);
37     if(n>N)
38         return ;
39     DFS(2*n,cnt);
40     DFS(2*(n+1),cnt+1);
41     return;
42 }
43 */
44 int niconiconi(int n){
45     int cnt;
46     for(cnt=0;n;n>>=1)
47         cnt+=(n&1);
48     return cnt;
49 }
50  
51 bool Do(){
52     if(scanf("%d",&N)==EOF)
53         return false;
54     //ans=999999;
55     //DFS(1,1);
56     printf("%d\n",niconiconi(N));
57 }
58  
59  
60  
61 int main(){
62     #if debug
63     freopen("in.txt","r",stdin);
64     #endif
65     while(Do());
66     return 0;
67 }

 

转载于:https://www.cnblogs.com/ohyee/p/5375107.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值