专栏文章
声速幂
算法·理论参与者 5已保存评论 12
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 8 条
- 当前快照
- 1 份
- 快照标识符
- @mj4joaf2
- 此快照首次捕获于
- 2025/12/14 01:03 2 个月前
- 此快照最后确认于
- 2026/02/14 01:29 6 天前
省流:固定底数;对于 , 预处理, 询问。
前言
前置知识:快速幂 光速幂也可以在里面找到。
符号表示:在本文中, 为指数的数域,。 为底数。
对于结果有模数的幂,注意到 ,因此有 。对于素模数有 。
由于洛谷上没有讲光速幂的文章,这里简要讲一下。
光速幂
对于很小的 ,我们可以 地预处理出幂的值。
对于较大的 则不行。
取 ,我们知道
因此我们预处理 和 ,则 。
注意到取 时,复杂度是最佳的。
原理
同样解决固定底数的幂,对于 ,可以在 的时间内预处理一个底数,在 的时间内回答一个询问。
我们考虑处理一个 进制的快速幂。很明显,这个 进制的数一共有 位。
比如 :
进制快速幂的每一位都有 个值,这个值很大,不能立即算出,需要预处理。
对于这个例子,我们要预处理出 (〇), (一)。
对于这个例子,我们要预处理出 (〇), (一)。
考虑缩小 ,比如 :
这时候,我们就需要预处理出
- (〇),
- (一),
- (二),
- (三)。
考虑如何预处理。我们令 。可以验证,这就是以上预处理的内容。换言之,。
- 首先枚举计算 。
- 对于 ,明显有 。
- 。
形式化地,
显然是 的。
对于询问,只需要将这个 进制的指数 的每一位预处理出的值相乘。
形式化地,
很明显是 的。
例题
例题
令 。
给定 ,求 。
。
令 ,则当 时,,否则不能降幂。因为此时 ,故没有降幂。
此题中,,我们取 。
参考代码
CPP// C++14(GCC 9) O2 洛谷 IDE
#include <bits/stdc++.h>
using namespace std;
typedef size_t Z;
constexpr Z N = 5 + 1e9, M = 65535, S = 65536;
Z a, b, cur = 1, n, ax[64], ans;
Z f0[S], f1[S], f2[S], f3[S];
int main() {
cin >> a >> b >> n;
// 预处理
// ax[i] = pow(a, pow(2, i));
ax[0] = a;
for (Z i = 1; i < 64; ++i)
ax[i] = ax[i - 1] * ax[i - 1];
Z x0 = ax[0], x1 = ax[16],
x2 = ax[32], x3 = ax[48];
// f##j[i] = pow(a, i * pow(65536, j));
f0[0] = f1[0] = f2[0] = f3[0] = 1;
for (Z i = 1; i < 65536; ++i) {
f0[i] = f0[i - 1] * x0;
f1[i] = f1[i - 1] * x1;
f2[i] = f2[i - 1] * x2;
f3[i] = f3[i - 1] * x3;
}
for (Z i = 1; i <= n; ++i) {
cur *= b;
ans ^= f0[cur & M] * f1[cur >> 16 & M]
* f2[cur >> 32 & M] * f3[cur >> 48 & M]; // 询问
}
cout << ans;
return 0;
}
运行时间约 毫秒,无氧 毫秒,空间 kb,正确性已经过对比验证。
一般快速幂应该过不了。
相关推荐
评论
共 12 条评论,欢迎与作者交流。
正在加载评论...