heky 发布的文章

一、n的二进制表示中第k位是几
第一步:将n右移k位,即 n >> k,把第k位移到最低位。
第二步:通过与运算获取最低位的值,即 n & 1,判断第k位是0还是1。

二、lowbit(x):返回x的最低位1及其后所有0所组成的数值

例如:
x = 1010(二进制) lowbit(x) = 10
x = 101000(二进制) lowbit(x) = 1000

原理:
lowbit(x) 的计算公式是 x & -x。

解释:

  • 首先,-x 等于 ~x + 1,这是二进制表示中取反加一的结果(即补码)。
  • 当我们将x与-x进行按位与运算时,结果会保留x中最低位的1,并将其他位清零。

举例说明:
x = 1010010101000
~x = 0101101010111
-x = ~x + 1 = 0101101011000(补码)
x & -x = 0000000001000

这表明lowbit(x) = 1000。

应用:
可以用lowbit(x)来计算x(二进制)中有多少个1。

最近在学react还有go。
在我的不懈坚持之下,终于让前后端通信了,可喜可贺。
icon_wink.gif

puts("") 的作用是换行。

puts 函数是 C 标准库中的一个函数,用于将字符串输出到标准输出设备(通常是控制台),并在输出结束后自动换行。

其函数原型如下:

int puts(const char *str);

主要功能:

  1. 输出字符串puts 函数会将传入的字符串参数 str 输出到标准输出(通常是终端或控制台)。
  2. 自动换行:与 printf 不同的是,puts 函数在输出完字符串后会自动添加一个换行符(\n),因此你不需要手动加上换行。
  3. 返回值:如果输出成功,puts 返回一个非负值。如果发生错误,返回 EOF(表示 End of File 或错误)。

示例:

puts("Hello, World!");

输出为:

Hello, World!

(并且会自动换行)

区别:

  1. printf 不同,puts 只适用于输出 字符串,而不能像 printf 那样支持格式化输出(例如整型、浮点型等)。
  2. puts 函数在输出完毕后 自动换行,而 printf 需要你手动添加换行符 \n

所以puts("") 实际上是输出一个空字符串,然后自动换行。

这个程序的主要目的是计算 (b!) 的末尾有多少个连续的0。当前的算法通过模拟阶乘的乘法来计算整个大数阶乘,再统计结果中末尾的0的数量。然而,当 (b) 很大时,这种直接模拟阶乘的方法会导致运行时间和空间效率较低,容易超时。

实际上,计算一个数的阶乘末尾有多少个0并不需要真的计算出整个阶乘。阶乘末尾0的数量实际上取决于阶乘中因子5的数量(因为2的数量总是比5多)。因此,可以采用数学方法来计算。

优化方法

计算 (b!) 末尾0的数量的核心在于统计从1到(b)中,能够被5整除的数的个数,以及更高次方(如25, 125, …)的贡献。具体的公式为:

Pasted image 20240925122937.png
一直计算到 Pasted image 20240925123033.png

优化后的代码

#include<iostream>
using namespace std;

int main() 
{
    int b;
    cin >> b;
    int count = 0;
    for (int i = 5; i <= b; i *= 5) 
    {
        count += b / i;
    }
    cout << count << "\n";
    return 0;
}

解释

  1. i 从5开始,每次乘以5,直到 ( i > b ) 为止。
  2. b / i 表示当前阶乘数范围内包含多少个可以被当前的5次方整除的数。
  3. 将每一步的结果累加即可得到 (b!) 中因子5的总数,这就是末尾0的数量。

这种方法的时间复杂度是 (O(\log b)),相比原算法效率极高,能轻松处理非常大的 (b) 值,从而避免超时问题。