快速幂——二分求法

本文介绍了一种使用二分幂算法高效计算幂次的方法,并提供了详细的C语言代码实现。通过位运算来加速幂次计算过程,适用于计算机科学与程序设计竞赛等场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天睡觉前在做二分图匹配,睡醒后突然想到了二分幂,然后就写了下,还真给写出来了,权当做模板吧。。。


#include <stdio.h>

int js(int n,int xh)
{
    int sum = 1;
    for(int i = 0; i < xh; i++)
    {
        sum *= n;
    }
    return sum;
}

int main()//输入的数据是两个数分别是n,m,结果是n^m(m >= 0)
{
    int n,m,sum,cnt;
    while(scanf("%d%d",&n,&m),n || m)
    {
        sum = 1;
        cnt = 0;
        while(m != 0)
        {
            sum *= js(n,(m & 1) * (1 << cnt));
            m >>= 1;
            cnt++;
        }
        printf("%d\n",sum);
    }

    return 0;
}

最新模板:


#include <stdio.h>

int fz(int x,int y)
{
    int sum = 1;
    for(int i = 0;i < y;i++)
    {
        sum *= x;
    }
    return sum;
}

int js(int n,int m)
{
    int sum = 1,cnt = 1;
    while(m)
    {
        sum *= fz(n,(m & 1) * cnt);
        m >>= 1;
        cnt <<= 1;
    }
    return sum;
}

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        printf("%d\n",js(n,m));
    }
    return 0;
}


### 替代除法运算的方法 在C语言中,可以通过其他更高效的计算方式来替代传统的除法运算。以下是几种常见的替代方法: #### 1. 使用位移操作替代特定的除法 对于某些特殊的除法场景(例如被2、4、8等2的幂次方整除),可以直接使用右移操作符 `>>` 来完成。这是因为二进制中的右移相当于将数值除以2的幂次方。 ```c // 将变量a除以8的操作可以用右移3位代替 int result = a >> 3; // 等价于 a / 8 ``` 这种方法适用于无符号数或已知符号不会影响结果的情况[^3]。 --- #### 2. 利用乘法逆元替代除法 当除数是一个固定的常量时,可以预先计算出它的倒数并存储下来,之后通过乘法和截断的方式模拟除法效果。这种方式特别适合ARM架构下的优化,因为ARM处理器支持快速的乘法指令而缺乏高效的硬件除法单元[^1]。 假设要计算 \( \text{result} = \frac{\text{dividend}}{\text{divisor}} \),则可先求得 divisor 的近似倒数 reciprocal,再执行如下操作: \[ \text{result} = (\text{dividend} \times \text{reciprocal}) >> N \] 其中N取决于精度需求以及数据宽度。 示例代码展示如何用乘法替换简单的固定除法: ```c #include <stdint.h> uint32_t divide_by_5(uint32_t dividend) { const uint64_t multiplier = UINT64_C(0xcccccccd); // (2^32)/5 rounded up return (uint32_t)((uint64_t)dividend * multiplier >> 32); } ``` 此函数实现了无需调用实际除法指令即可完成对任意非负整型输入值做五之一处理的功能。 --- #### 3. 预定义查找表(LUT) 针对频繁使用的少量不同类型的除法表达式,创建预设好的映射关系表格也是一种可行的选择。比如如果程序里经常需要用到某几个特殊比率,则提前准备好对应的结果集能够显著减少运行时间开销。 下面的例子展示了构建一个小规模LUT来进行简单数转换的过程: ```c const float lut[] = {0.f, 0.5f, 0.3333333f, 0.25f}; // 假设有这些常见比例 float fast_divide(int numerator, int denominator_index){ if(denominator_index >= sizeof(lut)/sizeof(*lut)) return -1; return numerator * lut[denominator_index]; } ``` 这里我们假定母总是有限集合内的成员,并且已经将其可能对应的浮点形式存入数组当中以便即时检索利用[^2]。 --- #### 4. 定点数表示与运算 另一种策略涉及采用定点数学技术而非传统意义上的浮点数表现手法。“定点”意味着所有的数字都被视为具有隐含的小数点位置——通常是在最低有效位之前若干固定数量的位置处设定好这个虚拟割线。这样做的好处是可以充利用标准CPU寄存器所提供的全字宽参与所有基本四则运算过程而不必担心额外引入复杂度较高的FPUs所带来的性能损失问题。 举个例子来说就是把原来打算当作实数对待的数据对象重新解释成扩大一定倍率后的纯整数值进行后续各项逻辑推导直至最终输出前才恢复原状呈现给外界使用者看到预期形态的答案为止。 --- ### 总结 以上介绍了四种主要途径用来规避直接运用耗时较长的标准库函数版本或者底层汇编级实现路径上的常规/百号操作子行为模式。具体选择哪一种方案需视乎应用场景的具体特性如目标平台资源状况、所需精确程度等因素综合考量决定最佳实践方向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值