A : log2(N)
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 205 Solved: 36
Description
给你一个数N,请你找出最大的的整数k,满足 2k ≤ N
Input
1 ≤ N ≤ 1019
Output
输出k并换行
Sample Input
6
Sample Output
2
Hint
注意精度问题
一、题目大意
输入一个数N,要求输出log2N(向下取整)
二、思路
1、储备知识:
a、四种取整函数
函数 | 功能 | 例子 |
---|---|---|
floor () | 向负无穷取整 | floor(2.5)=2,floor(-2.4)=-3 |
ceil() | 向正无穷取整 | ceil(2.5)=3,ceil(-2.4)=-2 |
trunc() | 向零取整 | trunc(2.5)=2,trunc(-2.4)=-2 |
round() | 四舍五入 | round(2.5)=3,round(-2.4)=-2 |
b.对数函数log()与指数函数pow()
函数 | 功能 | 例子 |
---|---|---|
log(N) | 输出以e为底N的对数 | log(2.7)=0.993252 |
pow(a,n) | 输出底数为a的n次方 | pow(2,3)=8 |
注1:以上6种函数头文件:#include<math.h>
注2:数学上log26=log(6)/log(2)(要实现数学上的对数,可以用商来表示)
注3:如果可以尽量全都敲一遍,巩固记忆。
2、思路
思路A
将log2(N)转化成log(N)/log(2)
然后再向下取整。也就是使用floor函数
对应代码如下。
#include<iostream>
#include<math.h>
using namespace std;
int main()
{
double n;
cin>>n
cout<<floor(log(n)/log(2))<<endl;
return 0;
}
注:这个程序逻辑没有问题,但由于log()函数内参数为浮点数,取整的时候,可能出现精度丢失的问题。导致oj判错。
思路B
模拟逼近运算,将输入的数字num循环与20~264比较,当第一次出现2i>num时
则必然存在:num>=2i-1
在这里,抹去所有的浮点数,保证不会出现精度丢失的情况,算正统的解法
#include<iostream>
using namespace std;
int main()
{
long long n,ans=1;
cin>>n;
for(int i=0;i<=64;i++)
{
if(n<ans){cout<<i-1<<endl;break;}//ans=2的i次方
ans*=2;
}
return 0;
}
思路C
输入一个数n后,循环到0~64,当pow(2,i)大于n时输出i-1,原理等同于思路B
#include<iostream>
#include<math.h>
using namespace std;
int main()
{
long long n;
cin>>n;
for(int i=0;i<=64;i++)
if(n<pow(2,i)){cout<<i-1<<endl;break;}
return 0;
}
思路A与思路C两个代码逻辑上没有问题,但由于log()与pow()内的参数为浮点数,在转化成整数的时候可能会出现精度丢失的问题,如果出题人恶意卡人是可能会wa的,所以在需要取整的时候幂函数和对数函数最好不用,而是全用整数。