数据结构与算法 | 青训营笔记

81 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第1天

刚接触算法 放一个快速幂模板 基于位运算的思想


题目大意

求 a 的 b 次方对 p 取模的值。

输入格式

三个整数 a,b,p ,在同一行用空格隔开。 输出格式

输出一个整数,表示a^b mod p的值。 数据范围 0≤a,b≤109 \ 1≤p≤109

输入样例:

3 2 7

输出样例:

2

ACcode

// Problem: a^b

// Contest: AcWing

// URL: https://www.acwing.com/problem/content/91/

// Memory Limit: 32 MB

// Time Limit: 1000 ms

//

// Powered by CP Editor (https://cpeditor.org)



#include <algorithm>

#include <cmath>

#include <cstring>

#include <iostream>

#include <sstream>

#include <vector>

#define endl '\n'

#define ios \

ios::sync_with_stdio(0); \

cin.tie(0); \

cout.tie(0);

#define DEBUG printf("Passing [%s] in LINE %d\n", __FUNCTION__, __LINE__)

//

using namespace std;

const int N = 2e5 + 10;

const int minN = 1e3 + 10;

int n, m, t;

// char cha1[minN], cha2[minN];

// string s, str1[N], str2[N];

\


// int a[N], b[N];

int tot, le[1], rt[1], key[1], value[1];

\


void debug() // splay

{

int i;

for (i = 0; i <= tot; i++)

printf("Node[%d] le=%d rt=%d key=%d value=%d\n", i, le[i], rt[i], key[i],

value[i]);

}

\


bool cmp(int a, int b) { return a > b; }

\


void solve() {

// 快速幂

int a, b, p;

cin >> a >> b >> p;

int res = 1 % p;

while (b) {

if (b & 1) res = res * 1ll * a % p;

a = a * 1ll * a % p; // 处理b的下一位

b >>= 1; // 上面已经处理了个位,把个位去掉

}

cout << res;

}

\


signed main() {

// int n, k;

// scanf("%d %d", &n, &k);

// for(int i = 1;i <= n; ++i) cin >> a[i];

solve();

return 0 ^ 0;

}

以及分享一个讲二分答案 讲的很清晰的一个帖子


~ 建议那天的 [跟着月影学js] 改名为 [跟着月影学算法]


一个 acwing 上的 推公式步骤

因为 pow 函数得到的值是 double 类型,有效数字只有 15∼16 位,并不能求出精确值。这道题目是让我们求出精确值对某个数的余数,所以这道题我们可以使用快速幂来做。 如果 b在二进制下有 k 位,其中第 i(0≤i≤k)位的数字是 ci,有: b=ck−1 2 k−1+ck−2 2 k−2+⋅⋅⋅+c0 2 0

于是:

ab=ack−1 2 k−1 ∗ ack−2 2 k−2 ∗ ⋅⋅⋅ ∗ ac0 2 0

又因为:

a2i=(a2i−1)2 所以我们可以通过上一次计算的结果来计算下一次计算的结果。这公式这么复杂,到底怎么理解呢?手动模拟一下就可以啦!