洛谷 P5091 【模板】欧拉定理
题目
题目描述
给你三个正整数,a,m,ba,m,b,你需要求:
a^b \bmod mabmodm
输入格式
一行三个整数,a,m,ba,m,b
输出格式
一个整数表示答案
输入输出样例
输入 #1
2 7 4
输出 #1
2
输入 #2
998244353 12345 98765472103312450233333333333
输出 #2
5333
说明/提示
注意输入格式,a,m,ba,m,b 依次代表的是底数、模数和次数
样例1解释:
2^4 \bmod 7 = 224mod7=2
输出2
数据范围:
对于全部数据:
1≤a≤10^91≤a≤109
1≤b≤10^{20000000}1≤b≤1020000000
1≤m≤10^61≤m≤106
分析
- 首先,我们需要知道欧拉定理,扩展欧拉定理
- 欧拉定理 aφ(m) ≡ 1 mod m
- 扩展欧拉定理 b≥φ(m)时,a^b ≡ a^(b mod φ(m) )+ φ(m) mod m
- 那我们来证明下欧拉定理
- 定义一个n=φ(m)
- 设x1,x2,x3...xn是小于m与m互质的数
- 然后我们再设k为与m互质的数 gcd(k,m)=1
- 那么再构成一个数列A{kx1,kx2,kx3...kxn}
- 我们尝试证明A中有两个数mod m是相等的
- 假设 ak≡bk (mod m)
- ak-bk=qm q为m的倍数
- (a-b)k=qm 所以左边mod m是等于0的
- 但是k与m互质所以是不成立的 证毕
- 我们再证明A中所以数mod m 都是与 m 互质的
- 首先 kx=k*x
- k是与m互质的 x也是与m互质的
- 所以gcd(k,m)=1,gcd(x,m)=1
- 所以k*x都不包含m的因子
- 也就是说k*x/m是个最简分数
- gcd(kx,m)=1,gcd(kx%m,m)=1;欧几里得定理 证毕
- 还有就是如何求欧拉函数
- 欧拉筛是n
- 我们筛合数就是nsqrt(n)
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 using namespace std; 5 int read(int mod) 6 { 7 int s=0,w=1,flag=0; 8 char c=getchar(); 9 while (c<'0'||c>'9') if (c=='-') w=-1; else c=getchar(); 10 while (c<='9'&&c>='0') 11 { 12 s=(s*10+c-'0'); 13 if (s>=mod) 14 { 15 s%=mod; 16 flag=1; 17 } 18 c=getchar(); 19 } 20 if (flag) s+=mod; 21 return s; 22 } 23 long long ksm(long long a,long long b,long long mod) 24 { 25 long long x=a,ans=1; 26 while (b) 27 { 28 if (b&1!=0) ans=ans*x%mod; 29 x=x*x%mod; 30 b>>=1; 31 } 32 return ans; 33 } 34 int main () 35 { 36 int a,b,m; 37 cin>>a>>m; 38 int tmp=m,phi=m; 39 for (int i=2;i*i<=m;++i) 40 { 41 if (tmp%i==0) 42 { 43 phi=phi-phi/i; 44 while (tmp%i==0) 45 { 46 tmp/=i; 47 } 48 } 49 } 50 if (tmp>1) phi=phi-phi/tmp; 51 b=read(phi); 52 cout<<ksm(a,b,m); 53 }
为何要逼自己长大,去闯不该闯的荒唐