欧拉函数
定义:欧拉函数指对于以正整数n,phi[n]=1~n(不包括n)中与n互质的正整数的个数。
下面给出求解欧拉函数的两种方法:直接求解和打表法;
//直接求解欧拉函数,基于容斥定理
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;
}
#define maxn 1000001
int phi[maxn];
void Init() //打表求一个区间内所有的欧拉函数值
{
phi[1]=1;
for(int i=2;i<maxn;i++)
phi[i]=i;
for(int i=2;i<maxn;i++)
if(phi[i]==i)
for(int j=i;j<maxn;j+=i)
phi[j]=phi[j]/i*(i-1); //先进行除法是为了防止中间数据的溢出
}
欧拉函数性质
欧拉函数性质:
1:若p是素数,则(phi(p)=p-1);
2:对于两个素数,(phi(p*q)=p*q-1);
3:对于(m=n^k),(phi(m)=phi(n^k)=n^k-n^{k-1});
欧拉定理:
[当a与m互质时有: a^{φ(m)} ≡ 1(mod m)
]
扩展欧拉定理:
[当b >= φ(m)时有: a^b ≡ a^{(b\%φ(m)+φ(m))}(mod m)
]
一道扩展欧拉的应用题:给你三个正整数a, m, b,你需要求:(a^b\% m),范围a:(10^9), m:(10^8), b:(10^{20000000})。直接扩展欧拉定理即可,对b边读边取模, 再特判一下b与phi(m)的大小即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
int gcd(int a,int b) { return b == 0 ? a : gcd(b, a % b); }
LL a, m, mod;
string b;
LL phi(LL n){
LL 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;
}
LL qpow(LL a, LL k, LL mod){
LL ans = 1 % mod;
while(k){
if(k & 1) ans = ans * a % mod;
k >>= 1;
a = a * a % mod;
}
return ans;
}
int main()
{
cin >> a >> m;
cin >> b;
mod = phi(m);
int ans = 0, len = b.length(), ok = 0;
for(int i = 0; i < len; ++i){
ans = ans * 10;
ans = ans + b[i] - '0';
if(ans >= mod) ok = 1;
ans %= mod;
}
b = ans % mod + mod;
if(!ok) b -= mod; //如果ans(及b mod phi(m))是小于b的,那么不能用扩展欧拉, 这是直接算a^b即可
cout << qpow(a, b, m) << endl;
system("pause");
}