信奥赛C++提高组csp-s之数论基础专题课:欧拉函数和欧拉定理2(编程案例实践)

信奥赛C++提高组csp-s之数论基础专题课:欧拉函数和欧拉定理2(编程案例实践)

信奥赛C++中的欧拉函数和欧拉定理是数论基础专题中重要内容。上次内容我们了讲解其数学原理,并举数学例子帮大家做了深入理解。本次课我们将讲解编程案例实践。

扩展欧拉定理

题目描述

给你三个正整数, a , m , b a,m,b a,m,b,你需要求: a b   m o d   m a^b \bmod m abmodm。

输入格式

一行三个整数, a , m , b a,m,b a,m,b。

输出格式

一个整数表示答案。

输入输出样例 1
输入 1
复制代码
2 7 4
输出 1
复制代码
2
输入输出样例 2
输入 2
复制代码
998244353 12345 98765472103312450233333333333
输出 2
复制代码
5333
说明/提示

注意输入格式, a , m , b a,m,b a,m,b 依次代表的是底数、模数和次数。

【样例 1 1 1 解释】
2 4   m o d   7 = 2 2^4 \bmod 7 = 2 24mod7=2。

【数据范围】

对于 100 % 100\% 100% 的数据, 1 ≤ a ≤ 10 9 1\le a \le 10^9 1≤a≤109, 1 ≤ b ≤ 10 20000000 , 1 ≤ m ≤ 10 8 1\le b \le 10^{20000000},1\le m \le 10^8 1≤b≤1020000000,1≤m≤108。

思路分析

本题要求计算 a b   m o d   m a^b \bmod m abmodm,其中 b 可能是一个长度高达 2 × 10 7 2\times 10^7 2×107 的巨大整数,无法直接用整数存储。必须利用扩展欧拉定理来降低指数规模:

a b ≡ { a b ( m o d m ) b < φ ( m ) a   b   m o d   φ ( m ) + φ ( m ) ( m o d m ) b ≥ φ ( m ) a^b \equiv \begin{cases} a^b \pmod{m} & b < \varphi(m) \\[1ex] a^{\,b \bmod \varphi(m) + \varphi(m)} \pmod{m} & b \ge \varphi(m) \end{cases} ab≡{ab(modm)abmodφ(m)+φ(m)(modm)b<φ(m)b≥φ(m)

其中 φ ( m ) \varphi(m) φ(m) 是欧拉函数( 1 ≤ m ≤ 10 8 1\le m\le 10^8 1≤m≤108,可用试除法求出)。

算法步骤:

  1. 读入 (a, m) 和字符串 (b)。
  2. 特判 m = 1:直接输出 0。
  3. 计算 φ ( m ) \varphi(m) φ(m)。
  4. 判断 b 与 φ ( m ) \varphi(m) φ(m) 的大小关系:
    • 若 b 的十进制长度 ≤ 9 \le 9 ≤9,则可将 b 转为整数与 φ ( m ) \varphi(m) φ(m) 比较,若 b < φ ( m ) b < \varphi(m) b<φ(m),指数取 b 本身;否则指数取 b   m o d   φ ( m ) + φ ( m ) b \bmod \varphi(m) + \varphi(m) bmodφ(m)+φ(m)。
    • 若 b 的长度 (> 9),则 b 一定不小于 φ ( m ) \varphi(m) φ(m),只需计算 b   m o d   φ ( m ) b \bmod \varphi(m) bmodφ(m),指数取该余数加 φ ( m ) \varphi(m) φ(m)。
  5. 用快速幂计算 a 指数   m o d   m a^{\text{指数}} \bmod m a指数modm 并输出。

代码实现

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

// 计算欧拉函数 phi(n)  (n <= 1e8)
int phi(int n) {
    int res = n;
    for (int i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            res = res / i * (i - 1);
            while (n % i == 0) n /= i;
        }
    }
    if (n > 1) res = res / n * (n - 1);
    return res;
}

// 快速幂:计算 a^b % mod
ll qpow(ll a, ll b, ll mod) {
    ll r = 1 % mod;
    while (b) {
        if (b & 1) r = (r * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return r;
}

int main() {
    int a, m;
    string b;
    cin >> a >> m >> b;

    if (m == 1) {          // 模数为1,任何数模1都是0
        cout << 0 << endl;
        return 0;
    }

    int p = phi(m);         // p = φ(m)
    ll e;                   // 最终指数

    int len = b.size();
    if (len <= 9) {         // b 可以用整数表示,直接比较
        ll B = stoll(b);
        if (B < p) e = B;
        else {
            // 虽然 B >= p,但为了保险仍取余数并加上 p
            e = B % p + p;
        }
    } else {                // b 长度 >9,肯定 >= p,只需计算余数
        ll r = 0;
        for (char c : b) {
            r = (r * 10 + (c - '0')) % p;
        }
        e = r + p;
    }

    ll ans = qpow(a % m, e, m);
    cout << ans << endl;

    return 0;
}

功能分析

  • 欧拉函数计算 :使用试除法,时间复杂度 O ( m ) O(\sqrt{m}) O(m ),对于 m ≤ 10 8 m\le 10^8 m≤108完全可行。
  • 大整数处理 :通过字符串读入 b,利用长度比较和逐位取模避免溢出,同时正确判断 b 与 φ ( m ) \varphi(m) φ(m) 的大小关系,满足扩展欧拉定理的使用条件。
  • 指数确定 :根据比较结果,选择直接使用 b 或 b   m o d   φ ( m ) + φ ( m ) b \bmod \varphi(m) + \varphi(m) bmodφ(m)+φ(m) 作为最终指数,保证定理适用。
  • 快速幂 :使用二进制拆分,时间复杂度 O ( log ⁡ 指数 ) O(\log \text{指数}) O(log指数),指数不超过 2 φ ( m ) ≤ 2 × 10 8 2\varphi(m) \le 2\times 10^8 2φ(m)≤2×108,运行极快。
  • 边界处理:特判 m=1,避免后续运算;取模前先将 a 对 m 取余,防止中间溢出。

更多系列知识,请查看专栏:《信奥赛C++提高组csp-s知识详解及案例实践》:
https://blog.csdn.net/weixin_66461496/category_13113932.html


各种学习资料,助力大家一站式学习和提升!!!

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"##########  一站式掌握信奥赛知识!  ##########";
	cout<<"#############  冲刺信奥赛拿奖!  #############";
	cout<<"######  课程购买后永久学习,不受限制!   ######";
	return 0;
}

1、csp信奥赛高频考点知识详解及案例实践:

CSP信奥赛C++动态规划:
https://blog.csdn.net/weixin_66461496/category_13096895.html点击跳转

CSP信奥赛C++标准模板库STL:
https://blog.csdn.net/weixin_66461496/category_13108077.html 点击跳转

信奥赛C++提高组csp-s知识详解及案例实践:
https://blog.csdn.net/weixin_66461496/category_13113932.html

2、csp信奥赛冲刺一等奖有效刷题题解:

CSP信奥赛C++初赛及复赛高频考点真题解析(持续更新):https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转

信奥赛C++提高组csp-s初赛&复赛真题题解(持续更新)
https://blog.csdn.net/weixin_66461496/category_13125089.html

3、GESP C++考级真题题解:

GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转

GESP(C++ 七级+八级)真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13117178.html

4、csp/信奥赛C++,完整信奥赛系列课程(永久学习):

https://edu.csdn.net/lecturer/7901 点击跳转

· 文末祝福 ·

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"跟着王老师一起学习信奥赛C++";
	cout<<"    成就更好的自己!       ";
	cout<<"  csp信奥赛一等奖属于你!   ";
	return 0;
}
相关推荐
总斯霖2 小时前
P15445永远在一起!题解(月赛T2)
数据结构·c++·算法·深度优先
Yupureki2 小时前
《C++实战项目-高并发内存池》4.CentralCache构造
c语言·开发语言·c++·单例模式·github
样例过了就是过了2 小时前
LeetCode热题100 全排列
数据结构·c++·算法·leetcode·dfs
2401_898075122 小时前
分布式系统监控工具
开发语言·c++·算法
OKkankan3 小时前
撕 STL 系列:封装红黑树实现 mymap 和 myset
java·c++·算法
ab1515173 小时前
3.15二刷基础90、105、106、110
数据结构·c++·算法
寻寻觅觅☆3 小时前
东华OJ-进阶题-10-分解质因数(C++)
数据结构·c++·算法
Darkwanderor3 小时前
数据结构——ST表和RMQ问题
数据结构·c++·动态规划·st表·rmq问题
是梦终空1163 小时前
模板编译期机器学习
开发语言·c++·算法