赞
踩
正文开始之前先说一说废话,在学习数论系列的算法有一种勿入高端局的感觉,其实也正常,毕竟一些定理从名字上拗口,如果见识多了了解多了,再说出一些以洋人名字命名的定理公式总会让人觉得很牛逼,其实学习的内容并不难,只要思路跟着走。
标题标注的即为讲解顺序,后面内容的讲解需要前面内容的基础,内容较多,分为两篇讲解,本篇主要讲解费马小定理、欧拉函数、欧拉定理。
看似乎不难,那再详细讲解一下:
p 为素数(质数),且 a 与 p 互素(即 gcd(a,p)= 1 ),则有
- 注:
是在对 p 取模的情况下恒等于 1
设 p 是一个 质数,且 a 是不为 p 的倍数的数。
设一个序列 A = { 1, 2, 3, ... , p-1 },则有 ( p 是质数 ) ,
因为 a 不是 p 的倍数,所以无论 1 ~ p - 1 之间谁乘 a 都是独一无二,即 每一个 独一无二
且都不是 p 的倍数,所以 在 mod p 的情况下 每一个 也独一无二(难理解的在这一点)
可以理解为从 0 开始每次都加 a 直到恰好小于 p ,再多一个 a 就大于 p 时,再加一个 a
再 mod p 会使得结果不为 0 ,再回到第一步每次都加 a ,因为初始值不再为 0 所以每次加 a 都和
mod p 之前每次加 a 的数都不一样,如此可证的在 mod p 的情况下 每一个 也独一无二
设 则
至此证明完成,还有其他证明方法,在此不再说明。
定义比较简单,但是可能不知道怎么求?确实让人头大,要一个一个判断前面没一个数是否和 n 互质吗?
这个编辑器好难用,还是直接放图片了
设 ,p 为质数,则
根据唯一分解定理(不了解的可以先看我之前发的数论基础的素数部分(tip:素数与质数是一样的,只是叫法不同)算法学习过程——数论基础)可得
设 (符号表示连乘)
,可以用 for 循环实现连乘
- #include <cmath>
-
- int phi(int n)//求欧拉函数的值
- {
- int res = n;
- int m = sqrt(x);
- for(int i = 2;i <= m;++i)//相当于质因数分解
- {
- if(x % i)continue;
- res = res / i *(i-1);
- while(x % i == 0)x /= i;//由于每个数都只乘一次,所以把多余部分去掉
- }
- if(n > 1)res = res / n * (n-1);//如果最后不为1,则表示最后一个数也是质因数
- return res;
- }
也可以改写成以下形式,会提升一点点效率
- #include <cmath>
-
- int phi(int n)//求欧拉函数的值
- {
- int res = n;
- for(int i = 2;i <= n / i;++i)//相当于质因数分解 防止i*i超出限制
- {
- if(x % i)continue;
- res = res / i *(i-1);
- while(x % i == 0)x /= i;//由于每个数都只乘一次,所以把多余部分去掉
- }
- if(n > 1)res = res / n * (n-1);//如果最后不为1,则表示最后一个数也是质因数
- return res;
- }
定义较为简单,只有一个公式
当 m 是质数的时候有 ,与费马最小定理一致。
思路:按照所学,似乎 n - 1 就是可以满足答案的数,可是让我们寻找最小,在满足题目等式成立的情况下可以去 n - 1 的因数中寻找答案。
- #include "bits/stdc++.h"
- using namespace std;
- const int MOD = 998244353;
- const int p = 1e6+7;
- const int N = 209;
- #define int long long
- int a, n;
-
- int qmi(int a,int b,int p)//快速幂
- {
- int res = 1;
- while(b)
- {
- if(b & 1)res = res * a % p;
- a = a * a % p;
- b >>= 1;
- }
- return res;
- }
- int phi(int x)//求欧拉函数的值
- {
- int res = x;
- int m = sqrt(x);
- for(int i = 2;i <= m;++i)
- {
- if(x % i)continue;
- res = res / i *(i-1);
- while(x % i == 0)x /= i;
- }
- if(x > 1)res = res / x * (x-1);
- return res;
- }
- void solve(){
- cin >> a >> n;
- int ph = phi(n);
- int ans = ph;
- int m = sqrt(n);
- for(int i = 1;i <= m;++ i)
- {
- if(ph % i)continue;
-
- if(qmi(a,i,n) == 1)ans = min(ans,i);
- if(i != ph / i)//两个因数不一样
- {
- if(qmi(a,ph / i,n) == 1)ans = min(ans,ph / i);
- }
- }
- cout << ans << '\n';
- }
- signed main() {
- ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(0);
- int _ = 1;
- //cin >> _;
- while(_--)solve();
- return 0;
- }

这类模板题只要样例调试对了一般不会出错,大家放心。
初步数论中欧拉函数、欧拉定理,自用复习以及分享给大家,有任何问题可以留言或私信。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。