“卓见杯”郑州轻工业大学2020级新生程序设计大赛 第一题详细题解

由于原文的解析过于简单 ( 大佬不说人话) ,此文章在原文的基础上加上了评论与额外的解析,旨在分享自己学习的成果

原文链接:https://blog.csdn.net/qq_45874814/article/details/115185844

2779: 小A与泉水

题目描述

小A遇到了一座神奇的泉水,在泉水中洗涤会大幅增加他的精力。在一次洗涤中,泉水增加力量的数值为当前力量二进制表示中的最低位的1对应的值。
例如:
如果当前力量为9(1001 最低位1对应的值为1),增加的力量为1;
如果当前力量为12(1100 最低位1对应的值为100),增加的力量为4。
小A想要将他的力量变为2的幂次数,他需要在泉水中洗涤多少次呢?

输入

多样例测试
第一行输入T(T<=100,000),代表样例数;
剩余T行,每行输入一个数n(n<1,000,000,000)代表小A当前的力量。

输出

对于每次询问,输出小A需要在泉水中洗涤的次数。

样例输入

4
1
2
3
5

样例输出

0
0
1
2

#include 
using namespace std;
typedef long long ll;

int jud(ll n){
	int ans = 0;
	while(n > 1){
		if(n%2 == 1){
			ans++; n++; n=n/2;
		}else n = n/2;
	}
	return ans;
}
int main(){
	ll t, a;
	scanf("%lld",&t);
	while(t--){
		scanf("%lld",&a);
		printf("%d\n",jud(a));
	}
}

解析:

这首先要对题目进行数学分析,但我数学不好,对二进制不够熟悉,所以这一题没有做出来。(这就是强者的世界吗?)

jud函数就是这个程序的精髓,大佬已经参破这一题的要点了。

废话结束,开始分析:

如果你想让一个数变为2的幂次数,最好的方法就是把它转化二进制,这样便于观察与操作。

按照题目的思路,我们尝试做一下题目

9的二进制数为1001,假设这是小A的力量。

洗一次后,他的力量为10,即为1010,

再洗一次,他的力量为12,即为1100,

再来一次,他的力量为16,即为10000.

结果为3

我想,聪明的你已经看破了这道题的本质了。

如果还是不懂的话,我再来举个例子

假设小A的力量为41,二进制为101001,

洗一次后,他的力量为42,即为101010,

再洗一次,他的力量为44,即为101100,

接下来是48,即11000,

最后,是64,即100000.

结果为4

到这里,如果还是不懂的话,咱们来看看这个题二进制计算的规律:

以41为例,它的二进制为101001,末尾不是0,加一,1;

101010,末尾是0,砍去0,得10101,加一得10110,2;

10110,末尾是0,砍去0,得1011,加一得1100,3;

1100。末尾是0,砍去所有1后面的0,得11,加一得100,4;

至此,计算完毕。

好,我们现在知道了这个题的解法,那么接下来,我们只需要将得到的算法转变为代码就可以了。

这里只需要注意:二进制中的砍去末尾的“0”的操作就是在十进制中除2的操作,进行每次加一操作就是在模拟一次洗泉水,输出加一得次数即为结果

这下看大佬的jud函数就可以知道,大佬的算法有多精妙了,题目也迎刃而解。

你可能感兴趣的:(zzulioj)