题目
题目描述
给你三个正整数,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 }