n次方
1、问题描述
计算 an
2、算法分析
先将 n 变一变,寻找新的计算路径。预处理就是变治法的根本。
如果单纯循环执行 n 次相乘,那么时间复杂度为 O(n)。可以利用二进制幂大大改进效率。
主要思路是:将十进制的 n 转换成二进制的数组序列 b[]。二进制幂求解有两种方法:从左至右二进制幂和从右至左二进制幂。
从左至右二进制幂
变换:an = a(b[n]2m + ... + b[0]20)
先求 n 的二进制串,如:n = 5 => 1 0 1,那么 b[2] = 1, b[1] = 0, b[0] = 1
二进制求 n 的伪代码:
Horner(b[0...n], x)
k = b[n]
for i = n-1 downto 0 do
p = x*k + b[i]
return p
那么 n 用作 a 的指数时意义是什么样的呢:
ap = a1
for i = n - 1 downto 0 do
ap = a(2p+b[i])
从右至左二进制幂
n 变换方法与上面相同,然后从 b[0] -> b[n] 方向逐步求解。
时间复杂度:O(logn)
3、代码实现
#include <stdio.h>
#include <stdlib.h>
/**
* @brief 返回 x 的二进制串(数组)
*/
int GetBinArray(int x, int arr[], int length)
{
int idx = 0;
while(x > 0) {
// 获取末位的二进制
arr[idx++] = (x & 1) ? 1 : 0;
if (idx == length)
break;
// 右移两位
x = x >> 1;
}
return idx;
}
/**
* @brief a^n = a^(b[n]2^n + ... + b[0]2^0)= a^(b[n]2^n)* ... * a^b[0]。 b 数组元素不是 1 就是 0
*/
int Pow_Bin_RightToLeft(int number, int power)
{
if (power == 0)
return 1;
int length = sizeof(int) * 8; // 32
int *pint = (int *)malloc(length);
// 获取幂的二进制数组
length = GetBinArray(power, pint, length);
int item = number;
int ret = 1;
for (int i = 0; i < length; i++) {
// 二进制值为 1,计入结果
if (pint[i] == 1)
ret *= item;
item *= item;
}
free(pint);
return ret;
}
/**
* @brief a^n = a^(b[n]2^n + ... + b[0]2^0)=((b[n]*2 + b[n-1])*X + ....)2 + b[0]。 b 数组元素不是 1 就是 0
*/
int Pow_Bin_LeftToRight(int number, int power)
{
if (power == 0)
return 1;
int length = sizeof(int)*8;
int *pint = (int *)malloc(length);
length = GetBinArray(power, pint, length);
int ret = number;
for (int i = length - 1 - 1; i >= 0; i--) {
ret *= ret;
if(pint[i] == 1)
ret *= number;
}
free(pint);
return ret;
}
int main()
{
int num = 8, power = 6;
int ret1 = Pow_Bin_RightToLeft(num, power);
int ret2 = Pow_Bin_LeftToRight(num, power);
printf("Pow_Bin_RightToLeft: %d^%d == %d\n", num, power, ret1);
printf("Pow_Bin_LeftToRight: %d^%d == %d\n", num, power, ret2);
return 0;
}
Pow_Bin_RightToLeft: 8^6 == 262144
Pow_Bin_LeftToRight: 8^6 == 262144
4、内容来源
n次方的更多相关文章
- [LeetCode] Super Pow 超级次方
Your task is to calculate ab mod 1337 where a is a positive integer and b is an extremely large posi ...
- [LeetCode] Power of Four 判断4的次方数
Given an integer (signed 32 bits), write a function to check whether it is a power of 4. Example: Gi ...
- [LeetCode] Power of Three 判断3的次方数
Given an integer, write a function to determine if it is a power of three. Follow up:Could you do it ...
- [LeetCode] Power of Two 判断2的次方数
Given an integer, write a function to determine if it is a power of two. Hint: Could you solve it in ...
- [LeetCode] Pow(x, n) 求x的n次方
Implement pow(x, n). 这道题让我们求x的n次方,如果我们只是简单的用个for循环让x乘以自己n次的话,未免也把LeetCode上的想的太简单了,一句话形容图样图森破啊.OJ因超时无 ...
- 剑指Offer面试题:10.数值的整数次方
一.题目:数值的整数次方 题目:实现函数double Power(doublebase, int exponent),求base的exponent次方.不得使用库函数,同时不需要考虑大数问题. 在.N ...
- GDUFE-OJ 1203x的y次方的最后三位数 快速幂
嘿嘿今天学了快速幂也~~ Problem Description: 求x的y次方的最后三位数 . Input: 一个两位数x和一个两位数y. Output: 输出x的y次方的后三位数. Sample ...
- 《剑指offer》面试题11: 数值的整数次方
面试题11: 数值的整数次方 剑指offer面试题11,题目如下 实现函数double power(double base,int exponent),求base的exponent次方, 不得使用库 ...
- 打出10的n次方,上标,下标等处理方法(mac)
我使用mac系统遇到的需求,需要在项目中显示10的6次方 用来做单位,找了很多方案,word等文本编辑工具很好实现(word是使用ctrl + shift + =)(mac 版的word是 Comm ...
- 计算2的N次方&&计算e
2的N次方 注意:这里在处理的时候并没有用循环来处理,而是用移位的做法. n<<4 就是 n*2^4 ,所以在本例中只需要写 1<<time (time是要求的 ...
随机推荐
- 压力测试(二)-Jmeter基本介绍
1.Jmeter基本介绍和使用场景 简介 1.压测不同的协议和应用 1) Web - HTTP, HTTPS (Java, NodeJS, PHP, ASP.NET, …) 2) SOAP / RES ...
- 【Amaple教程】6. 路由配置
在 第1节<启动路由> 章节中为了能让单页应用顺利跑起来,我们提前介绍了简单的路由配置方法.我们已了解路由配置的目的是指定不同的url下对应的 模块节点(也叫做模块容器)内应该显示哪个模块 ...
- Ubuntu 系统下如何安装pip3工具
一.[导读]Ubuntu 系统内置了 Python2 和 Python3 两个版本的开发环境,却没有内置相应的 pip3 管理工具,本文将介绍如何在Ubuntu下如何快速安装 pip3 工具,并升级到 ...
- 【翻译】.NET 5 Preview 1 发布
.NET 5 Preview 1 发布 去年年底,我们发布了.NET Core 3.0和3.1.这些版本添加了桌面应用程序模型Windows Forms(WinForms)和WPF,ASP.NET B ...
- 大型Java进阶专题(四) 设计模式之工厂模式
前言 今天开始我们专题的第三课了,开始对设计模式进行讲解,本章节介绍:了解设计模式的由来,介绍设计模式能帮我们解决那些问题以及剖析工厂模式的历史由来及应用场景.本章节参考资料书籍<Sprin ...
- 在kubernetes1.17.2上结合ceph部署efk
简绍 应用程序和系统日志可以帮助我们了解集群内部的运行情况,日志对于我们调试问题和监视集群情况也是非常有用的.而且大部分的应用都会有日志记录,对于传统的应用大部分都会写入到本地的日志文件之中.对于容器 ...
- 测试必知必会系列- Linux常用命令 - mv
21篇测试必备的Linux常用命令,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1672457.html 移动当 ...
- *fetch(_, { call, put }) { --- generator
effects: { *fetch(_, { call, put }) { const response = yield call(queryUsers); yield put({ type: 'sa ...
- docker:一文学基础使用
目录 docker介绍 安装与镜像源配置 CentOS7 安装 设置镜像源 补充: 简单使用例子 基础概念 四个概念 镜像概念补充: 容器概念补充: 常用命令: 查看docker信息 镜像操作 容器操 ...
- 启动/关闭oracle服务
写一个脚本就可以很方便的打开服务和关闭服务,但是记住要以管理员的身份运行哦! 首先建立两个文件:启动.txt 和关闭.txt [在下面代码里启动的服务名称可能版本不一样,有可能名字不一样,自己对照看看 ...