数学杀我
对于一个正整数 x x x,小于 x x x且和 x x x互质的正整数的个数,记做 φ ( x ) \varphi(x) φ(x)。其中 φ ( 1 ) \varphi(1) φ(1)被定义为 1 1 1。
φ ( x ) = x ∏ p ∣ x p − 1 p \varphi(x)=x\prod_{p|x}\frac{p-1}p φ(x)=xp∣x∏pp−1
部分性质:
根据通式,枚举 x x x的质因数。可枚举 x \sqrt x x以内的质因数,若存在大于 x \sqrt x x的质因数则额外处理。
时间复杂度: O ( n ) O(\sqrt n) O(n)
int phi(int x){
int ans=x;
for(int i=2;i*i<=x;i++)if(!(x%i)){
ans-=ans/i;
while(!(x%i))x/=i;
}
if(x>1)ans-=ans/x;
return ans;
}
Eratosthenes筛法筛质数:先假设所有的数都是质数。从小到大讨论,若 i i i是质数,则 i i i的倍数全部标记为合数。
用同样的方法求欧拉函数,先设 φ ( i ) = i \varphi(i)=i φ(i)=i,若 i i i是质数,则 i i i的倍数(即包含 i i i这个质因数的数)的函数值都要更新。
时间复杂度: O ( n log 2 log 2 n ) O(n\log_2\log_2n) O(nlog2log2n)
void make_prime(bool*mk,int n){
memset(mk,0,sizeof(mk));mk[1]=1;
for(int i=2;i<=n;i++)if(!mk[i])
for(int j=i+i;j<=n;j+=i)mk[j]=1;
}
void make_phi(int*phi,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);
}
Euler筛法筛质数:每个合数仅被它的最小质因数筛去正好一次。
线性筛求欧拉函数利用了欧拉函数的一些性质( p p p为质数):
时间复杂度: O ( n ) O(n) O(n)
void make_prime(bool*mk,int*p,int n){
memset(mk,0,sizeof(mk));mk[1]=1;
for(int i=2;i<=n;i++){
if(!mk[i])p[++tot]=i;
for(int j=1;j<=tot&&i*p[j]<=n;j++){
mk[i*p[j]]=1;
if(!(i%p[j]))break;
}
}
}
void make_phi(int*phi,bool*mk,int*p,int n){
memset(mk,0,sizeof(mk));mk[1]=phi[1]=1;
for(int i=2;i<=n;i++){
if(!mk[i])p[++tot]=i,phi[i]=i-1;
for(int j=1;j<=tot&&i*p[j]<=n;j++){
mk[i*p[j]]=1;
if(i%p[j])phi[i*p[j]]=phi[i]*(p[j]-1);
else{phi[i*p[j]]=phi[i]*p[j];break;}
}
}
}
GCD的个数(NKOJ 3684)
问题描述
给定两个正整数 n n n, m m m, 求满足下列两个条件的 x x x的个数:
条件1: 1 ⩽ x ⩽ n 1\leqslant x\leqslant n 1⩽x⩽n
条件2: g c d ( x , n ) ⩾ m gcd(x,n)\geqslant m gcd(x,n)⩾m
输入格式
一行,两个整数 n n n和 m m m
输出格式
一行,一个整数,表示所求结果
样例输入
10 2
样例输出
6
提示
2 ⩽ n ⩽ 1000000000 , 1 ⩽ m ⩽ N 2\leqslant n\leqslant 1000000000,1\leqslant m\leqslant N 2⩽n⩽1000000000,1⩽m⩽N
先考虑满足 x ⩽ n x\leqslant n x⩽n且 g c d ( x , n ) = d gcd(x,n)=d gcd(x,n)=d的 x x x的个数,显然 g c d ( x d , n d ) = 1 gcd(\frac xd,\frac nd)=1 gcd(dx,dn)=1
∴ x d \therefore\frac xd ∴dx为 ⌊ n d ⌋ \lfloor\frac nd\rfloor ⌊dn⌋内的与 ⌊ n d ⌋ \lfloor\frac nd\rfloor ⌊dn⌋互质的数,总共有 φ ( ⌊ n d ⌋ ) \varphi(\lfloor\frac nd\rfloor) φ(⌊dn⌋)个。
于是只需枚举 n n n的因数 d d d,当 d ⩾ m d\geqslant m d⩾m时答案增加 φ ( ⌊ n d ⌋ ) \varphi(\lfloor\frac nd\rfloor) φ(⌊dn⌋)。由于 n n n较大,可以把枚举量减少到 n \sqrt n n。特殊情况特殊处理。
#include
typedef long long LL;
LL phi(LL x){
LL ans=x;
for(LL i=2;i*i<=x;i++)if(!(x%i)){
ans=ans-ans/i;
while(!(x%i))x=x/i;
}
if(x>1)ans=ans-ans/x;
return ans;
}
int main(){
LL n,m,ans=0;
scanf("%lld%lld",&n,&m);
for(LL d=1;d*d<=n;d++){
if(d>=m&&!(n%d))ans+=phi(n/d);
if(d*d<n&&!(n%d)&&n/d>=m)ans+=phi(d);
}
printf("%lld\n",ans);
return 0;
}
如果 p p p是素数,且 a a a与 p p p互质,即 g c d ( a , p ) = 1 gcd(a,p)=1 gcd(a,p)=1,那么
a p − 1 ≡ 1 ( m o d p ) a^{p-1}\equiv1\pmod p ap−1≡1(modp)
证明:
有小于质数 p p p的 p − 1 p-1 p−1个数构成的集合 A = { 1 , 2 , 3 , … , p − 1 } A=\{1,2,3,\ldots,p-1\} A={1,2,3,…,p−1},显然 A A A中的数都与 p p p互质。
将集合 A A A中的数乘以 a a a并对 p p p取模,放入集合 B B B,于是 B = { a m o d    p , 2 a m o d    p , 3 a m o d    p , … , ( p − 1 ) a m o d    p } B=\{a\mod p,2a\mod p,3a\mod p,\ldots,(p-1)a\mod p\} B={amodp,2amodp,3amodp,…,(p−1)amodp}
B B B中的数都小于 p p p,并且由于 g c d ( a , p ) = 1 gcd(a,p)=1 gcd(a,p)=1,这些数都与 p p p互质,得到 A = B A=B A=B。
将两个集合的元素分别相乘得 ( p − 1 ) ! ≡ ( p − 1 ) ! a p − 1 ( m o d p ) (p-1)!\equiv(p-1)!a^{p-1}\pmod p (p−1)!≡(p−1)!ap−1(modp)
∴ a p − 1 ≡ 1 ( m o d p ) \therefore a^{p-1}\equiv1\pmod p ∴ap−1≡1(modp)。
因为 a p − 1 ≡ 1 ( m o d p ) a^{p-1}\equiv1\pmod p ap−1≡1(modp),那么 a ⋅ a p − 2 ≡ 1 ( m o d p ) a\cdot a^{p-2}\equiv1\pmod p a⋅ap−2≡1(modp)
所以 a p − 2 a^{p-2} ap−2就是 a a a关于模 p p p的乘法逆元。
费马小定理是欧拉定理的一种特殊情况。
若 a , n a,n a,n为正整数,且 a , n a,n a,n互质,即 g c d ( a , n ) = 1 gcd(a,n)=1 gcd(a,n)=1,则有:
a φ ( n ) ≡ 1 ( m o d n ) a^{\varphi(n)}\equiv1\pmod n aφ(n)≡1(modn)
证明过程参考费马小定理。
a a a与 n n n互质时,可用欧拉定理降幂。
a b m o d    n = a b m o d    φ ( n ) m o d    n a^b\mod n=a^{b\mod\varphi(n)}\mod n abmodn=abmodφ(n)modn
一般地, b ⩾ φ ( n ) b\geqslant\varphi(n) b⩾φ(n)时:
a b m o d    n = a b m o d    φ ( n ) + φ ( n ) m o d    n a^b\mod n=a^{b\mod\varphi(n)+\varphi(n)}\mod n abmodn=abmodφ(n)+φ(n)modn