欧拉函数
欧拉函数
欧拉函数的定义
欧拉函数 φ ( n ) \varphi(n) φ(n) :对于一个正整数 n n n ,小于 n n n 且与 n n n 互质的正整数的个数。
欧拉函数的积性证明
笛卡尔乘积是指在数学中,两个集合 X X X 和 Y Y Y 的笛卡尔积(Cartesian product),又称直积,表示为 X × Y X × Y X×Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员,例如 { 1 , 2 } × { a , b } = { ( 1 , a ) , ( 1 , b ) , ( 2 , a ) , ( 2 , b ) } \{1,2\}\times \{a,b\}=\{(1,a),(1,b),(2,a),(2,b)\} {1,2}×{a,b}={(1,a),(1,b),(2,a),(2,b)}.
简化剩余系也称既约剩余系或缩系,是 m m m 的完全剩余系中与 m m m 互素的数构成的子集,如果模m的一个剩余类里所有数都与 m m m 互素,就把它叫做与模 m m m 互素的剩余类。
引理: ( a , x ) = 1 (a,x)=1 (a,x)=1 , ( b , x ) = 1 (b,x)=1 (b,x)=1 ⟺ ⟺ ⟺ ( a b , x ) = 1 (ab,x)=1 (ab,x)=1 ;
证明:
设
A
A
A 为模
a
a
a 的既约剩余系,
B
B
B 为模
b
b
b 的既约剩余系,
C
C
C 为模
a
b
ab
ab 的既约剩余系,
定义映射
f
f
f :
C
→
A
×
B
C→A×B
C→A×B:
f
(
z
)
=
(
z
m
o
d
a
,
z
m
o
d
b
)
f(z)=(z\space mod\space a,z\space mod\space b)
f(z)=(z mod a,z mod b)
因为
gcd
(
a
,
b
)
=
1
\gcd(a,b)=1
gcd(a,b)=1,由中国剩余定理可知,对于任意的
(
x
,
y
)
∈
A
×
B
(x,y)∈A×B
(x,y)∈A×B,存在唯一的
z
∈
C
z∈C
z∈C 使得:
z
≡
x
(
m
o
d
a
)
,
z
≡
y
(
m
o
d
b
)
z≡x\space(mod\space a),\space z≡y\space(mod\space b)
z≡x (mod a), z≡y (mod b)
这表明 f f f 是双射。
因为 ∣ C ∣ = φ ( a b ) |C|=\varphi(ab) ∣C∣=φ(ab), ∣ A × B ∣ = φ ( a ) ⋅ φ ( b ) ∣A×B∣=\varphi(a)⋅\varphi(b) ∣A×B∣=φ(a)⋅φ(b) 且 f f f 为双射;
所以 φ ( a b ) = φ ( a ) ⋅ φ ( b ) \varphi(ab)=\varphi(a)⋅\varphi(b) φ(ab)=φ(a)⋅φ(b)
欧拉函数的性质
性质1:积性函数, a a a 与 b b b 互质,则
φ ( a b ) = φ ( a ) φ ( b ) \varphi(ab)=\varphi(a)\varphi(b) φ(ab)=φ(a)φ(b)
性质2:若 p p p 为素数,则
φ ( p ) = p − 1 \varphi(p)=p−1 φ(p)=p−1
性质3:若 p p p 为素数, k k k 为正整数,则
φ ( p k ) = p k − p k − 1 = p k − 1 ( p − 1 ) \varphi(p^{k})=p^{k}−p^{k-1}=p^{k-1}(p−1) φ(pk)=pk−pk−1=pk−1(p−1)
简单证明一下:因为 p p p 为素数,所以只有当一个数 q q q 的因数包含 p p p 时, q q q 与 p p p 不互质,所以在小于 p k p^{k} pk 的数中,只有 { p , 2 p , 3 p ⋯ p k − 1 p } \{p,2p,3p\cdots p^{k-1}p\} {p,2p,3p⋯pk−1p} 与 p p p 不互质,一共 p k − 1 p^{k-1} pk−1 个,所以与 p k p^{k} pk 互质的有 p k − p k − 1 p^{k}-p^{k-1} pk−pk−1 。
性质4:质因数分解形式的公式
φ ( n ) = n ∏ i = 1 c ( 1 − 1 p i ) \varphi(n)=n\prod_{i=1}^{c}(1- \frac{1}{p_{i}}) φ(n)=ni=1∏c(1−pi1)
证明: φ ( n ) = φ ( p 1 k 1 ) ⋅ φ ( p 2 k 2 ) ⋯ φ ( p c k c ) \varphi(n)=\varphi(p_{1}^{k_{1}})\cdot\varphi(p_{2}^{k_{2}})\cdots\varphi(p_{c}^{k_{c}}) φ(n)=φ(p1k1)⋅φ(p2k2)⋯φ(pckc)
⟹ φ ( n ) = ( p 1 k 1 − p 1 k 1 − 1 ) ⋅ ( p 2 k 2 − p 2 k 2 − 1 ) ⋯ ( p c k c − p c k c − 1 ) \implies\varphi(n)=(p_{1}^{k_{1}}-p_{1}^{k_{1}-1})\cdot(p_{2}^{k_{2}}-p_{2}^{k_{2}-1})\cdots(p_{c}^{k_{c}}-p_{c}^{k_{c}-1}) ⟹φ(n)=(p1k1−p1k1−1)⋅(p2k2−p2k2−1)⋯(pckc−pckc−1)
⟹ φ ( n ) = p 1 k 1 ( 1 − 1 p 1 ) ⋅ p 2 k 2 ( 1 − 1 p 2 ) ⋯ p c k c ( 1 − 1 p c ) \implies\varphi(n)=p_{1}^{k_{1}}(1- \frac{1}{p_{1}})\cdot p_{2}^{k_{2}}(1-\frac{1}{p_{2}})\cdots p_{c}^{k_{c}}(1- \frac{1}{p_{c}}) ⟹φ(n)=p1k1(1−p11)⋅p2k2(1−p21)⋯pckc(1−pc1)
⟹ φ ( n ) = n ( 1 − 1 p 1 ) ⋅ ( 1 − 1 p 2 ) ⋯ ( 1 − 1 p c ) \implies\varphi(n)=n(1- \frac{1}{p_{1}})\cdot (1-\frac{1}{p_{2}})\cdots (1- \frac{1}{p_{c}}) ⟹φ(n)=n(1−p11)⋅(1−p21)⋯(1−pc1)
⟹ φ ( n ) = n ∏ i = 1 c ( 1 − 1 p i ) \implies\varphi(n)=n\prod_{i=1}^{c}(1- \frac{1}{p_{i}}) ⟹φ(n)=n∏i=1c(1−pi1)
性质5:一个重要的恒等式
∑ d ∣ n φ ( d ) = n \sum_{d|n}\varphi(d)=n d∣n∑φ(d)=n
证明:设集合 S = { 1 , 2 , 3 , ⋯ , n } S=\{1,2,3,\cdots,n\} S={1,2,3,⋯,n},
对于每一个因子 d ∣ n d\space|\space n d ∣ n,定义子集 S d = { k ∈ S ∣ gcd ( k , n ) = d } S_{d}=\{k\in S \space |\space \gcd(k,n)=d\} Sd={k∈S ∣ gcd(k,n)=d},
也就是说 S d S_{d} Sd 是 S S S 中与 n n n 的最大公约数为 d d d 的数的集合。
根据 S d S_{d} Sd 集合定义,可知 k = d ⋅ m ( 1 ≤ m ≤ n d ) k=d\cdot m \space (1\le m\le \frac{n}{d}) k=d⋅m (1≤m≤dn),
由于 gcd ( k , n ) = d \gcd(k,n)=d gcd(k,n)=d,可推出 gcd ( m , n d ) = 1 \gcd(m,\frac{n}{d})=1 gcd(m,dn)=1,且满足该式的 m m m 有 φ ( n d ) \varphi(\frac{n}{d}) φ(dn) 个,
所以 ∣ S d ∣ = φ ( n d ) |S_{d}|=\varphi(\frac{n}{d}) ∣Sd∣=φ(dn),
由定义可得,
S
S
S 是所有
S
d
S_{d}
Sd 的并集,所有的
S
d
S_{d}
Sd 都不相交,即
S
=
⋃
d
∣
n
S
d
,
S
d
1
∩
S
d
2
=
∅
(
d
1
≠
d
2
)
S=\bigcup_{d|n}S_{d},S_{d_{1}}\cap S_{d_{2}}=\varnothing (d_{1}\not =d_{2})
S=d∣n⋃Sd,Sd1∩Sd2=∅(d1=d2)
因此
n
=
∣
S
∣
=
∑
d
∣
n
∣
S
d
∣
=
∑
d
∣
n
φ
(
n
d
)
=
∑
d
∣
n
φ
(
d
)
n=|S|=\sum_{d|n}|S_{d}|=\sum_{d|n}\varphi(\frac{n}{d})=\sum_{d|n}\varphi(d)
n=∣S∣=d∣n∑∣Sd∣=d∣n∑φ(dn)=d∣n∑φ(d)
欧拉函数的求法
单个数的欧拉函数值
由于只需要单个数,可以直接借助质因数分解后的公式(上文的性质4)直接计算,时间复杂度 O ( n ) O(\sqrt{n}) O(n),代码如下:
ll phi(ll x){ //typedef long long ll;
ll res=x;
for(ll i=2;i*i<=x;i++)//由于大于sqrt(n)的质因数最多只有一个,所以只需要枚举到sqrt(n),再特判即可
if(x%i==0){ //如果是质因数
res=res/i*(i-1);//先除后乘,防止爆long long
while(x%i==0) x/=i;//质因数分解
}
if(x!=1) res=res/x*(x-1);//若x最后的值不为1,证明存在比sqrt(n)大的质因数
return res;
}
埃氏筛打表求值
根据埃氏筛的性质,我们可以利用它,逐步筛去质因子的贡献,直接得到每个数的 φ ( n ) \varphi(n) φ(n),时间复杂度与埃氏筛求素数一致,均为 O ( n log log n ) O(n\space \log\space \log\space n) O(n log log n),代码如下:
void eratos(){
for(int i=2;i<maxx;i++){ //maxx是预处理的最大上限
if(E[i]) continue;//如果E[i]有值,证明它不是素数
for(int j=i;j<maxx;j+=i){ //筛去质数i的倍数j
if(!E[j]) E[j]=j;//赋成它自身的值
E[j]=E[j]/i*(i-1);//公式计算
}
}
return ;
}
欧拉筛打表求值
埃氏筛可降低时间复杂度,欧拉筛当然也可以,我们可以用欧拉函数的积性对欧拉筛进行改造,时间复杂度与欧拉筛求素数一致,均为 O ( n ) O(n) O(n),代码如下:
void oula(){
phi[1]=1; //初始化phi[1]
for(int i=2;i<=n;i++){
if(!st[i])//st[i]储存i是否被筛过,!st[i]说明i为素数
phi[i]=i-1,pri[++cnt]=i;//pri[i]是欧拉筛的素数集合
for(int j=1;j<=cnt;j++){
int x=i*pri[j];
if(x>n) break;
st[x]=1;
if(i%pri[j]==0){ //判断pri[j]与i是否互质
phi[x]=phi[i]*pri[j];//不互质时的计算方式(后面有证明)
break;//欧拉筛保证每一个合数只被筛一次的核心
}
phi[x]=phi[i]*(pri[j]-1);//pri[j]与i互质,直接利用积性
}
}
return ;
}
证明: φ ( n ) = φ ( p 1 k 1 ) ⋅ φ ( p 2 k 2 ) ⋯ φ ( p i k i ) ⋯ φ ( p c k c ) \varphi(n)=\varphi(p_{1}^{k_{1}})\cdot\varphi(p_{2}^{k_{2}})\cdots\varphi(p_{i}^{ki})\cdots\varphi(p_{c}^{k_{c}}) φ(n)=φ(p1k1)⋅φ(p2k2)⋯φ(piki)⋯φ(pckc)
⟹ φ ( p i ⋅ n ) = φ ( p 1 k 1 ) ⋅ φ ( p 2 k 2 ) ⋯ φ ( p i k i + 1 ) ⋯ φ ( p c k c ) \implies\varphi(p_{i}\cdot n)=\varphi(p_{1}^{k_{1}})\cdot\varphi(p_{2}^{k_{2}})\cdots\varphi(p_{i}^{ki+1})\cdots\varphi(p_{c}^{k_{c}}) ⟹φ(pi⋅n)=φ(p1k1)⋅φ(p2k2)⋯φ(piki+1)⋯φ(pckc)
⟹ φ ( p i ⋅ n ) = ( p 1 k 1 − p 1 k 1 − 1 ) ⋅ ( p 2 k 2 − p 2 k 2 − 1 ) ⋯ ( p i k i + 1 − p i k i ) ⋯ ( p c k c − p c k c − 1 ) \implies\varphi(p_{i}\cdot n)=(p_{1}^{k_{1}}-p_{1}^{k_{1}-1})\cdot(p_{2}^{k_{2}}-p_{2}^{k_{2}-1})\cdots(p_{i}^{k_{i+1}}-p_{i}^{k_{i}})\cdots(p_{c}^{k_{c}}-p_{c}^{k_{c}-1}) ⟹φ(pi⋅n)=(p1k1−p1k1−1)⋅(p2k2−p2k2−1)⋯(piki+1−piki)⋯(pckc−pckc−1)
⟹ φ ( p i ⋅ n ) = p 1 k 1 ( 1 − 1 p 1 ) ⋅ p 2 k 2 ( 1 − 1 p 2 ) ⋯ p i k i + 1 ( 1 − 1 p i ) ⋯ p c k c ( 1 − 1 p c ) \implies\varphi(p_{i}\cdot n)=p_{1}^{k_{1}}(1- \frac{1}{p_{1}})\cdot p_{2}^{k_{2}}(1-\frac{1}{p_{2}})\cdots p_{i}^{k_{i+1}}(1- \frac{1}{p_{i}})\cdots p_{c}^{k_{c}}(1- \frac{1}{p_{c}}) ⟹φ(pi⋅n)=p1k1(1−p11)⋅p2k2(1−p21)⋯piki+1(1−pi1)⋯pckc(1−pc1)
⟹ φ ( p i ⋅ n ) = p i ⋅ n ( 1 − 1 p 1 ) ⋅ ( 1 − 1 p 2 ) ⋯ ( 1 − 1 p i ) ⋯ ( 1 − 1 p c ) \implies\varphi(p_{i}\cdot n)=p_{i}\cdot n(1- \frac{1}{p_{1}})\cdot (1-\frac{1}{p_{2}})\cdots (1- \frac{1}{p_{i}})\cdots (1- \frac{1}{p_{c}}) ⟹φ(pi⋅n)=pi⋅n(1−p11)⋅(1−p21)⋯(1−pi1)⋯(1−pc1)
即: φ ( p i ⋅ n ) = p i ⋅ n ∏ i = 1 c ( 1 − 1 p i ) \varphi(p_{i}\cdot n)=p_{i}\cdot n\prod_{i=1}^{c}(1- \frac{1}{p_{i}}) φ(pi⋅n)=pi⋅ni=1∏c(1−pi1)
练习题
洛谷-P2023 Longge 的问题
题目背景
Longge 的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。
题目描述
现在问题来了:给定一个整数 n n n,你需要求出 ∑ i = 1 n gcd ( i , n ) \sum\limits_{i=1}^n \gcd(i, n) i=1∑ngcd(i,n),其中 gcd ( i , n ) \gcd(i, n) gcd(i,n) 表示 i i i 和 n n n 的最大公因数。
输入格式
输入只有一行一个整数,表示 n n n。
输出格式
输出一行一个整数表示答案。
对于 60 % 60\% 60% 的数据,保证 n ≤ 2 16 n\leq 2^{16} n≤216。
对于 100 % 100\% 100% 的数据,保证 1 ≤ n < 2 32 1\leq n< 2^{32} 1≤n<232。
Solution: 由题意可知 gcd ( i , n ) \gcd(i,n) gcd(i,n) 一定为 n n n 的一个因数,我们不妨将问题转化为,求对于每一个 d ∣ n d|n d∣n,从1到 n n n 有多少个数满足 gcd ( i , n ) = d \gcd(i,n)=d gcd(i,n)=d ,只需将每一个 d d d 乘上相应的次数求和即可;
可能满足上面等式的数一定有 i ∈ { d , 2 d , 3 d , ⋯ , d ⋅ n d } i\in\{d,2d,3d,\cdots,d\cdot \frac{n}{d}\} i∈{d,2d,3d,⋯,d⋅dn},我们令 i = k ⋅ d ( 1 ≤ k ≤ n d ) i=k\cdot d\space(1\leq k\leq \frac{n}{d}) i=k⋅d (1≤k≤dn),
又因为 n = d ⋅ n d n=d\cdot\frac{n}{d} n=d⋅dn,所以只有当 k k k 与 n d \frac{n}{d} dn 互质的时候, n n n 与 i i i 不存在更大的公因数,问题又转化成为求所有的 d ⋅ φ ( n d ) d\cdot\varphi(\frac{n}{d}) d⋅φ(dn) 之和
∑ i = 1 n gcd ( i , n ) = ∑ d ∣ n d ⋅ ∑ i = 1 n [ gcd ( i , n ) = d ] = ∑ d ∣ n d ⋅ φ ( n d ) \sum\limits_{i=1}^n \gcd(i, n)=\sum_{d|n}d\cdot\sum_{i=1}^{n}[\gcd(i,n)=d]=\sum_{d|n}d\cdot\varphi(\frac{n}{d}) i=1∑ngcd(i,n)=d∣n∑d⋅i=1∑n[gcd(i,n)=d]=d∣n∑d⋅φ(dn)
由于 2 32 2^{32} 232 以内数的因数很少,所以可以直接求单个数的欧拉函数值,代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
namespace zyx_{
ll n,ans;
ll phi(ll x){ //求取单个数的欧拉函数值
ll res=x;
for(ll 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); //别忘记大于sqrt(x)的质因数
return res;
}
int my_main(){
cin>>n;
for(ll i=1;i*i<=n;i++)
if(n%i==0){
ans+=i*phi(n/i);
if(i*i!=n) ans+=(n/i)*phi(i);
}
cout<<ans;
return 0;
}
}
int main(){
zyx_::my_main();
return 0;
}
洛谷-P2158 仪仗队
题目描述
作为体育委员,C 君负责这次运动会仪仗队的训练。仪仗队是由学生组成的 N × N N \times N N×N 的方阵,为了保证队伍在行进中整齐划一,C 君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。
现在,C 君希望你告诉他队伍整齐时能看到的学生人数。
输入格式
一行,一个正整数 N N N。
输出格式
输出一行一个数,即 C 君应看到的学生人数。
说明/提示
对于 100 % 100 \% 100% 的数据, 1 ≤ N ≤ 40000 1 \le N \le 40000 1≤N≤40000。
Solution: 我可以建立平面直角坐标系,不难发现,当某同学的坐标 ( x , y ) (x,y) (x,y) 不互质时,其与 C 君 ( 0 , 0 ) (0,0) (0,0) 之间的连线上,必定存在更小的正整数对 ( x , , y , ) (x^{,},y^{,}) (x,,y,),挡住了 C 君的视线,使得 ( x , y ) (x,y) (x,y) 的同学不能被看到,换句话说,该问题转化为求所有满足 x , y x,y x,y 互质的点对的个数,
我们不妨逐层累加点的个数,观察发现,对角线两侧的点对称分布,所以只需将每列的 φ ( i ) \varphi(i) φ(i) 乘以2求和即可,当然,不要忘记了对角线上还有一个同学!
#include<bits/stdc++.h>
using namespace std;
const int N=4e4+10;
namespace zyx_{
int n,sum=1,cnt,pri[N],phi[N];
bool st[N];
void oula(){ //欧拉筛打表欧拉函数
phi[1]=1;
for(int i=2;i<=n;i++){
if(!st[i]) pri[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt;j++){
int x=pri[j]*i;
if(x>n) break;
st[x]=true;
if(i%pri[j]==0){
phi[x]=phi[i]*pri[j];
break;
}
phi[x]=phi[i]*phi[pri[j]];
}
}
}
int my_main(){
cin>>n;
if(n==1){ //注意需要特判
cout<<0;
return 0;
}
oula();
for(int i=2;i<=n;i++){
sum+=phi[i-1]*2;
}
cout<<sum;
return 0;
}
}
int main(){
zyx_::my_main();
return 0;
}
洛谷-P2568 GCD
题目描述
给定正整数 n n n,求 1 ≤ x , y ≤ n 1\le x,y\le n 1≤x,y≤n 且 gcd ( x , y ) \gcd(x,y) gcd(x,y) 为素数的数对 ( x , y ) (x,y) (x,y) 有多少对。
输入格式
只有一行一个整数,代表 n n n。
输出格式
一行一个整数表示答案。
说明/提示
样例输入输出 1 解释
对于样例,满足条件的 ( x , y ) (x,y) (x,y) 为 ( 2 , 2 ) (2,2) (2,2), ( 2 , 4 ) (2,4) (2,4), ( 3 , 3 ) (3,3) (3,3), ( 4 , 2 ) (4,2) (4,2)。
数据规模与约定
对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 10 7 1\le n\le10^7 1≤n≤107。
来源:bzoj2818
Solution: 我们可以设 n n n 以内的素数集合为 P P P ,则 gcd ( x , y ) = d ( d ∈ P ) \gcd(x,y)=d\space(d\in P) gcd(x,y)=d (d∈P),根据最大公约数的定义,可以得到 x , y x,y x,y 均为 d d d 的倍数,即 x , y ∈ { d , 2 d , 3 d , ⋯ , d ⋅ n d } x,y\in\{d,2d,3d,\cdots,d\cdot\frac{n}{d}\} x,y∈{d,2d,3d,⋯,d⋅dn},不妨设 x = n ⋅ d , y = m ⋅ d ( 1 ≤ x , y ≤ n d ) x=n\cdot d,y=m\cdot d\space(1\leq x,y\leq \frac{n}{d}) x=n⋅d,y=m⋅d (1≤x,y≤dn),因为 d d d 为素数,所以 gcd ( n , m ) = 1 \gcd(n,m)=1 gcd(n,m)=1,
该问题可以转化为,对于每一个 n n n 以内的素数 d d d , n d \frac{n}{d} dn 范围内有多少种 ( n , m ) (n,m) (n,m) 的组合,使得 gcd ( n , m ) = 1 \gcd(n,m)=1 gcd(n,m)=1,求它们的加和,
由于 n , m n,m n,m 地位对等,我们可以固定住 n n n,来看 m m m,根据欧拉函数的定义,所有组合的个数即为1到 n d \frac{n}{d} dn 的所有 φ ( i ) \varphi(i) φ(i),只需在欧拉筛中加入前缀和即可,对于 m m m 也同理,但是由于 ( 1 , 1 ) (1,1) (1,1) 的存在,最后结果应乘以2再减去1;
a n s = ∑ d ∈ P { 2 [ ∑ i = 1 n d φ ( i ) ] − 1 } ans=\sum_{d\in P}\{2[\sum_{i=1}^{\frac{n}{d}}\varphi(i)]-1\} ans=d∈P∑{2[i=1∑dnφ(i)]−1}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e7+10;
namespace zyx_{
ll read(){ //快读快写
ll x=0;int f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
void print(ll x){
if(x<0) putchar('-'),x=-x;
if(x>9) print(x/10);
putchar(x%10+'0');
return ;
}
ll n,ans,cnt,pri[N];
ll phi[N],sumphi[N];
bool st[N];
void oula(){ //欧拉筛打表欧拉函数
sumphi[1]=phi[1]=1;
for(int i=2;i<=n;i++){
if(!st[i]) phi[i]=i-1,pri[++cnt]=i;
sumphi[i]=sumphi[i-1]+phi[i]; //直接计算前缀和
for(int j=1;j<=cnt;j++){
int x=i*pri[j];
if(x>n) break;
st[x]=1;
if(i%pri[j]==0){
phi[x]=phi[i]*pri[j];
break;
}
phi[x]=phi[i]*(pri[j]-1);
}
}
return ;
}
int my_main(){
n=read();
oula();
for(int i=1;i<=cnt;i++)
ans+=sumphi[n/pri[i]]*2-1;
print(ans);
return 0;
}
}
int main(){
zyx_::my_main();
return 0;
}
洛谷-P3601 签到题
题目背景
这是一道签到题!
建议做题之前仔细阅读数据范围!
题目描述
我们定义一个函数: qiandao ( x ) \operatorname{qiandao}(x) qiandao(x) 为小于等于 x x x 的数中,与 x x x 不互质的数的个数。
这题作为签到题,给出 l l l 和 r r r,求出:
∑ i = l r qiandao ( i ) m o d 666623333 \sum_{i=l}^r \operatorname{qiandao}(i)\bmod 666623333 i=l∑rqiandao(i)mod666623333
输入格式
一行两个整数, l l l、 r r r。
输出格式
一行一个整数表示答案。
输入输出样例 #1
输入 #1
233 2333
输出 #1
1056499
输入输出样例 #2
输入 #2
2333333333 2333666666
输出 #2
153096296
说明/提示
对于 30 % 30\% 30% 的数据, l , r ≤ 10 3 l,r\leq 10^3 l,r≤103。
对于 60 % 60\% 60% 的数据, l , r ≤ 10 7 l,r\leq 10^7 l,r≤107。
对于 100 % 100\% 100% 的数据, 1 ≤ l ≤ r ≤ 10 12 1 \leq l \leq r \leq 10^{12} 1≤l≤r≤1012, r − l ≤ 10 6 r-l \leq 10^6 r−l≤106。
Solution: 虽然 1 ≤ l ≤ r ≤ 10 12 1 \leq l \leq r \leq 10^{12} 1≤l≤r≤1012 的数据范围过大,但由于 r − l ≤ 10 6 r-l \leq 10^6 r−l≤106 ,我们可以考虑,将区间缩减到 [ 1 , 10 6 ] [ 1,10^{6}] [1,106] ,毕竟大于 n \sqrt{n} n 的质因数最多只有一个,可以先用欧拉筛找出 10 6 10^{6} 106 以内的所有素数,接着统计各个质数对区间 [ l , . r ] [l,.r] [l,.r] 的贡献即可,具体详解请看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=666623333;//模数
const int N=1e6+10;
namespace zyx_{
ll read(){ //快速读取
ll x=0;int f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
void print(ll x){ //快速输出
if(x<0) print('-'),x=-x;
if(x>9) print(x/10);
putchar(x%10+'0');
return ;
}
ll l,r,pri[N],phi[N],val[N];
bool st[N];
ll cnt,ans;
void oula(){ //欧拉筛筛素数
for(int i=2;i<=N;i++){
if(!st[i]) pri[++cnt]=i;
for(int j=1;j<=cnt&&pri[j]*i<=N;j++){
st[pri[j]*i]=true;
if(i%pri[j]==0) break;
}
}
return ;
}
int my_main(){
l=read(); r=read(); oula();
for(ll i=l;i<=r;i++){
phi[i-l]=val[i-l]=i; //初始化欧拉函数值与自身数值
}
for(ll i=1;i<=cnt&&pri[i]*pri[i]<=r;i++){
ll x=l/pri[i]*pri[i]+pri[i];//找到区间中质数pri[i]的最小的倍数
if(l%pri[i]==0) x=l;//特判
for(ll j=x;j<=r;j+=pri[i]){
phi[j-l]=phi[j-l]/pri[i]*(pri[i]-1);//欧拉函数公式
while(val[j-l]%pri[i]==0) val[j-l]/=pri[i];//质因数分解
}
}
for(ll i=l;i<=r;i++){
if(val[i-l]!=1) phi[i-l]=phi[i-l]/val[i-l]*(val[i-l]-1);//特殊处理存在大于sqrt(n)的质因数时的情况
(ans+=(i-phi[i-l])%mod)%=mod;//一定不要忘记了取模
}
print(ans);
return 0;
}
}
int main(){
zyx_::my_main();
return 0;
}


1191

被折叠的 条评论
为什么被折叠?



