「学习笔记」快速幂、快速乘与进制转化
快速幂
快速幂算法,可以比 cmath 库中的 pow 函数更快,还可以处理取模。
原理:
通过将指数拆分成几个因数相乘的形式,来简化幂运算。
具体操作:
将指数转化为二进制,如果这一位上是 \(1\),那就乘上这一位上的信息(即 \(x\) 的几次方,按照二进制的规则来即可)
| 二进制位数 | ...... | \(4\) | \(3\) | \(2\) | \(1\) |
|---|---|---|---|---|---|
| 对应的十进制 | ...... | \(x^3\) | \(x^2\) | \(x^1\) | \(x^0\) |
模拟一下以便于理解
e.g. 我们算 \(3\) 的 \(10\) 次方,\(10\) 的二进制为 \(1010\)
首先,最后一位为 \(0\),x = x * x % mod,因为二进制的每向左移一位,就更新为原来的二次方,右移。
现在,最后一位为 \(1\),那么答案乘上 \(x\) ,更新 \(x\) ,右移。 最后一位为 \(0\),x = x * x % mod,右移。
最后一位为1,ans = ans * x % mod, x = x * x % mod,右移,没有位数了,退出。
代码:
typedef long long ll;
ll qpow(ll x, ll y, ll mod) {
ll ans = 1;
while(y) {
if (y & 1) {
ans = 1ll * ans * x % mod;
}
y >>= 1;
x = 1ll * x * x % mod;
}
return ans % mod;
}
这里还有一种递归写法。
int qpow(int x, int y, int p) {
if (y == 0) return 1;
int z = qpow(x, y / 2, p);
z = 1ll * z * z % p;
if (y & 1) {
z = 1ll * z * x % p;
}
return z;
}
快速乘
它的原理与快速幂类似,只是快速幂是拆成几个数相乘,而快速乘是拆成几个数相加。
int qtimes(int x, int y, int p) {
if (y == 0) return 0;
int z = qtimes(x, y / 2, p);
z = (z + z) % p;
if (y & 1) {
z = (1ll * z + x) % p;
}
return z;
}
进制转化
原理
转十进制:
和上面快速幂的乘法操作很类似,就是每一位所代表的数字乘上这一位上的数字
举个例子
\(127(8)\) 转 \(10\) 进制
| 数位上的数 | \(1\) | \(2\) | \(7\) |
|---|---|---|---|
| 数位含义 | \(8^2\) | \(8\) | \(1\) |
\(127(8)\) 的十进制数就是 \(1 \times 8^2+2 \times 8+7 \times 1=87\)
转其他进制:
除法和取余,相信大家都学过,这里操作就是依靠除法和取余来实现的
举个例子
\(87(10)\) 转 \(8\) 进制
\[\begin{aligned}
87 \div 8 = 10&······余7\\
10 \div 8 = 1&······余2\\
1 \div 8 = 0&······余1
\end{aligned}
\]
将余数从下到上输出就行了
可以看一下这道例题,想知道怎么实现的可以参考以下代码
进制转化
代码:
#include<iostream>
#include<cstdio>
typedef long long ll;
using namespace std;
inline ll read()
{
ll x=0;
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x;
}
ll n,num,m;
int pd(char ch)
{
if(ch>='A'&&ch<='F') return ch-55;//字母转数字
if(ch>='0'&&ch<='9') return ch-'0';//直接返回数字
return -1;//不是数字,返回-1
}
inline void re(ll &x)
{
char ch=getchar();
if(pd(ch)==-1) ch=getchar();
while(~pd(ch))
{
x*=n;
x+=pd(ch);
ch=getchar();
}
}
ll pr(ll x)
{
if(x<10) return x+'0';
else return x-10+'A';
}
void print(ll k)//除,取模,倒叙输出
{
if(!k) return;
print(k/m);
putchar(pr(k%m));
}
int main()
{
n=read();
re(num);
m=read();
print(num);
return 0;
}
朝气蓬勃 后生可畏

浙公网安备 33010602011771号