1 1 1~ N N N中与 N N N互质的数的个数叫欧拉函数,记为 φ ( N ) \varphi(N) φ(N)
对 N N N分解质因数 N = p 1 c 1 ∗ p 1 c 1 ∗ . . . ∗ p k c k N=p_1^{c_1}*p_1^{c_1}*...*p_k^{c_k} N=p1c1∗p1c1∗...∗pkck
则有 φ ( N ) = N ∗ ( 1 − 1 p 1 ) ∗ ( 1 − 1 p 2 ) ∗ . . . ∗ ( 1 − 1 p k ) \varphi(N)=N*(1-\frac{1}{p_1})*(1-\frac{1}{p_2})*...*(1-\frac{1}{p_k}) φ(N)=N∗(1−p11)∗(1−p21)∗...∗(1−pk1)
特别的 φ ( 1 ) = 1 \varphi(1)=1 φ(1)=1
首先显然 1 1 1~ N N N中与 N N N互质的数就是
1 − N 1-N 1−N中不与 N N N含有相同质因子的数
那么先简单分析 N N N只有两个质因子的情况
假设 p , q p,q p,q为 N N N的质因子
那么 1 1 1~ N N N中p的倍数有 N p \frac{N}{p} pN个,q的倍数有 N q \frac{N}{q} qN个
我们自然要筛掉这些数 N − N p − N q N-\frac{N}{p}-\frac{N}{q} N−pN−qN
但是注意到这里面 p ∗ q p*q p∗q的倍数被减了两次
根据容斥原理,当然还要加回来
得 N − N p − N q + N p q N-\frac{N}{p}-\frac{N}{q}+\frac{N}{pq} N−pN−qN+pqN
对这个式子稍作变换
N − N p − N q + N p q N-\frac{N}{p}-\frac{N}{q}+\frac{N}{pq} N−pN−qN+pqN
⇓ \ \ \ \ \ \ \ \ \ \ \ \Downarrow ⇓
N ∗ ( 1 − 1 p − 1 q + 1 p q ) N*(1-\frac{1}{p}-\frac{1}{q}+\frac{1}{pq}) N∗(1−p1−q1+pq1)
⇓ \ \ \ \ \ \ \ \ \ \ \ \Downarrow ⇓
N ∗ ( 1 − 1 p ) ∗ ( 1 − 1 q ) N*(1-\frac{1}{p})*(1-\frac{1}{q}) N∗(1−p1)∗(1−q1)
只有两个质因数的情况证毕
到这里再用数学归纳法就可以拓展出上述得式子了
根据上述函数定义式
可以得到一个在分解质因数时同时求解单个欧拉函数的方法
时间复杂度为 O ( N ) O(\sqrt{N}) O(N)
int phi(int x)
{
int res=x;
for(int i=2;i*i<=x;++i)
{
if(x%i==0)
{
res=res/i*(i-1);
while(x%i==0) x/=i;
}
}
if(x>1) res=res/x*(x-1);
return res;
}
当然我们还可以有递推打表的计算
类似埃式筛法
每枚举到一个质数,就更新他的所有倍数的phi值
复杂度约为 O ( N l o g N ) O(NlogN) O(NlogN)
void euler(int n)
{
for(int i=1;i<=n;++i) phi[i]=i;
for(int i=2;i<=n;++i)
{
if(phi[i]==i)//发现一个质数
for(int j=i;j<=n;j+=i)//处理("筛")他的倍数
phi[j]=phi[j]/i*(i-1);
}
}
既然有类似埃式筛的递推方法
那么自然也不会少了线性筛
利用线性筛递推求解phi需要用到欧拉函数的两个性质
1.若有 p ∣ N p\mid N p∣N,且满足 p 2 ∣ N p^2\mid N p2∣N,则 φ ( N ) = φ ( N / p ) ∗ p \varphi(N)=\varphi(N/p)*p φ(N)=φ(N/p)∗p
2.若有 p ∣ N p\mid N p∣N,且一定不满足 p 2 ∣ N p^2\mid N p2∣N,则 φ ( N ) = φ ( N / p ) ∗ ( p − 1 ) \varphi(N)=\varphi(N/p)*(p-1) φ(N)=φ(N/p)∗(p−1)
这两条性质会在接下来给出证明
线性筛中每个合数n只会被他的最小质因子p筛一次
于是我们利用这点从 φ ( N / p ) \varphi(N/p) φ(N/p)递推到 φ ( N ) \varphi(N) φ(N)
复杂度为 O ( N ) O(N) O(N)
void Phi(int n)
{
phi[1]=1;
for(int i=2;i<=n;++i)
{
if(!vis[i]) prim[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt;++j)
{
if(i*prim[j]>n) break;
vis[i*prim[j]]=1;
if(i%prim[j]==0){ phi[i*prim[j]]=phi[i]*prim[j]; break;}
else phi[i*prim[j]]=phi[i]*phi[prim[j]];
}
}
}
1. ∀ N > 1 \forall N>1 ∀N>1, 1 1 1~ N N N中与 N N N互质的数的和为 N ∗ φ ( N ) / 2 N*\varphi(N)/2 N∗φ(N)/2
若有 x ∈ [ 1 , N ] x\in[1,N] x∈[1,N]且 g c d ( N , x ) = 1 ( 即 N 与 x 互 质 ) gcd(N,x)=1(即N与x互质) gcd(N,x)=1(即N与x互质)
根据更相减损术有 g c d ( N , x ) = g c d ( N , N − x ) gcd(N,x)=gcd(N,N-x) gcd(N,x)=gcd(N,N−x)
即 1 1 1~ N N N中与 N N N互质的数是成对出现的,对称轴就是 N / 2 N/2 N/2
也就是说 1 1 1~ N N N中与 N N N互质的数的平均值是 N / 2 N/2 N/2
而总和就是 N ∗ φ ( N ) / 2 N*\varphi(N)/2 N∗φ(N)/2
证毕
2.(1)当 a , b a,b a,b互质时,有 φ ( a ∗ b ) = φ ( a ) ∗ φ ( b ) \varphi(a*b)=\varphi(a)*\varphi(b) φ(a∗b)=φ(a)∗φ(b)
(2)对 N N N分解质因数 N = p 1 c 1 ∗ p 1 c 1 ∗ . . . ∗ p k c k N=p_1^{c_1}*p_1^{c_1}*...*p_k^{c_k} N=p1c1∗p1c1∗...∗pkck,则有 φ ( N ) = ∏ i = 1 k φ ( p i c i ) \varphi(N)=\prod_{i=1}^k\varphi(p_i^{c_i}) φ(N)=∏i=1kφ(pici)
这里的两条性质其实是直接应用了积性函数的性质
什么是积性函数
如果当 a , b a,b a,b互质时,有 f ( a ∗ b ) = f ( a ) ∗ f ( b ) f(a*b)=f(a)*f(b) f(a∗b)=f(a)∗f(b),则 f ( x ) 为 积 性 函 数 f(x)为积性函数 f(x)为积性函数
上述(1)是直接应用了定义
而(2)中将N分解质因数,显然分解的每一项都两两互质
根据积性函数定义也不难得出上述式子
3.(1)若有 p ∣ N p\mid N p∣N,且满足 p 2 ∣ N p^2\mid N p2∣N,则 φ ( N ) = φ ( N / p ) ∗ p \varphi(N)=\varphi(N/p)*p φ(N)=φ(N/p)∗p
(2)若有 p ∣ N p\mid N p∣N,且一定不满足 p 2 ∣ N p^2\mid N p2∣N,则 φ ( N ) = φ ( N / p ) ∗ ( p − 1 ) \varphi(N)=\varphi(N/p)*(p-1) φ(N)=φ(N/p)∗(p−1)
上述(1)中"若有 p ∣ N p\mid N p∣N,且满足 p 2 ∣ N p^2\mid N p2∣N"
说明N和N/p含有相同质因子
我们分析只含有两个质因子p和q的简单情况
φ ( N ) = N − N p − N q + N p q \varphi(N)=N-\frac{N}{p}-\frac{N}{q}+\frac{N}{pq} φ(N)=N−pN−qN+pqN
φ ( N / p ) = N p − N p 2 − N p q + N p 2 q \varphi(N/p)=\frac{N}{p}-\frac{N}{p^2}-\frac{N}{pq}+\frac{N}{p^2q} φ(N/p)=pN−p2N−pqN+p2qN
二者相除商为p
用数学归纳法扩展出k个质因子的情况可以得到相同结果
上述(2)中 “若有 p ∣ N p\mid N p∣N,且一定不满足 p 2 ∣ N p^2\mid N p2∣N”
说明 N N N和 N / p N/p N/p一定互质
根据积性函数定义有 φ ( N ) = φ ( N / p ) ∗ φ ( p ) \varphi(N)=\varphi(N/p)*\varphi(p) φ(N)=φ(N/p)∗φ(p)
因为p为素数,所以 φ ( p ) = p − 1 \varphi(p)=p-1 φ(p)=p−1
得 φ ( N ) = φ ( N / p ) ∗ ( p − 1 ) \varphi(N)=\varphi(N/p)*(p-1) φ(N)=φ(N/p)∗(p−1)
证毕
4. ∑ d ∣ n φ ( d ) = n \sum_{d|n}\varphi(d)=n ∑d∣nφ(d)=n
设 f ( n ) = ∑ d ∣ n φ ( d ) = n f(n)=\sum_{d|n}\varphi(d)=n f(n)=∑d∣nφ(d)=n
若有n,m互质,那么 f ( n m ) = ∑ d ∣ n m φ ( d ) = ∑ d ∣ n φ ( d ) ∗ ∑ d ∣ m φ ( d ) f(nm)=\sum_{d|nm}\varphi(d)=\sum_{d|n}\varphi(d)*\sum_{d|m}\varphi(d) f(nm)=∑d∣nmφ(d)=∑d∣nφ(d)∗∑d∣mφ(d)
可得 f ( n ) f(n) f(n)为积性函数
对于n的某个质因子 f ( p k ) = ∑ d ∣ p k φ ( d ) = φ ( 1 ) + φ ( p ) + φ ( p 2 ) + . . . + φ ( p k ) f(p^k)=\sum_{d|p^k}\varphi(d)=\varphi(1)+\varphi(p)+\varphi(p^2)+...+\varphi(p^k) f(pk)=∑d∣pkφ(d)=φ(1)+φ(p)+φ(p2)+...+φ(pk)
由上述3.(1)知该式为一个等比数列+1,公比为p
更具等比数列求和公式得 f ( p k ) = p k f(p^k)=p^k f(pk)=pk
所以 f ( n ) = ∏ i = 1 k f ( p k ) = ∏ i = 1 k p k = n f(n)=\prod_{i=1}^{k}f(p^k)=\prod_{i=1}^kp^k=n f(n)=∏i=1kf(pk)=∏i=1kpk=n
证毕
定理:若正整数 a , n a,n a,n互质,则有 a φ ( n ) ≡ 1 ( m o d    n ) a^{\varphi(n)}\equiv 1(\mod n) aφ(n)≡1(modn)
推论:若正整数 a , n a,n a,n互质,则对于任意正整数b,有 a b ≡ a b m o d    φ ( n ) ( m o d    n ) a^b\equiv a^{b\mod \varphi(n)}(\mod n) ab≡abmodφ(n)(modn)
扩展欧拉定理:
a , n ∈ Z a,n\in Z a,n∈Z,则 a b a^b ab { a b , b < φ ( n ) a b m o d    φ ( n ) + φ ( n ) , b > = φ ( n ) \left\{\begin{aligned}a^b,b<\varphi(n)\\ a^{b\mod\varphi(n)+\varphi(n) },b>=\varphi(n)\end{aligned}\right. {ab,b<φ(n)abmodφ(n)+φ(n),b>=φ(n) m o d    n \mod n modn
证明略
给定三个正整数 a , m , b a,m,b a,m,b,求 a b m o d    m a^b\mod m abmodm
1 ≤ a ≤ 1 0 9 , 1 ≤ b ≤ 1 0 20000000 , 1 ≤ m ≤ 1 0 6 1≤a≤10^{9},1≤b≤10^{20000000},1≤m≤10^6 1≤a≤109,1≤b≤1020000000,1≤m≤106
直接套用上述定理
#include
#include
#include
#include
#include
using namespace std;
typedef long long lt;
const int maxn=100010;
lt a,m,phi,rem;
lt read()
{
lt x=0;
char ss=getchar();
while(ss<'0'||ss>'9') ss=getchar();
while(ss>='0'&&ss<='9'){
x=x*10+ss-'0';ss=getchar();
if(x>=phi) rem=1,x%=phi;
}
return x;
}
lt calc(lt x)
{
lt res=x;
for(int i=2;i*i<=x;++i)
{
if(x%i==0)
{
res=res/i*(i-1);
while(x%i==0) x/=i;
}
}
if(x>1) res=res/x*(x-1);
return res;
}
lt qpow(lt aa,lt k)
{
lt res=1;
while(k){
if(k&1) res=(res*aa)%m;
aa=(aa*aa)%m; k>>=1;
}
return res;
}
int main()
{
scanf("%d%d",&a,&m);
phi=calc(m);
lt b=read();
if(rem) b+=phi;
printf("%d",qpow(a,b));
return 0;
}