XTU OJ 1355 Euler’s Totient Function(欧拉函数)
题目描述
对于整数n,定义
ϕ
(
n
)
ϕ(n)
ϕ(n)为小于或等于n,并与n互质的整数的个数,比如6,比它小的和它互质的数有1,5,所以
ϕ
(
6
)
=
2
ϕ(6)=2
ϕ(6)=2。 如果
n
=
p
1
k
1
⋅
p
2
k
2
⋅
…
⋅
p
m
k
m
n=p_1^{k_1}⋅p_2^{k_2}⋅…⋅p_m^{k_m}
n=p1k1⋅p2k2⋅…⋅pmkm,其中
p
i
p_i
pi为不相同的素数。 那么
ϕ
(
n
)
=
n
⋅
(
1
−
1
p
1
)
⋅
…
⋅
(
1
−
1
p
m
)
ϕ(n)=n⋅(1−\frac1{p_1})⋅…⋅(1−\frac1{p_m})
ϕ(n)=n⋅(1−p11)⋅…⋅(1−pm1)。
我们定义
f
(
a
,
b
)
=
∑
i
=
a
b
ϕ
(
i
)
f(a,b)=∑^b_{i=a}ϕ(i)
f(a,b)=∑i=abϕ(i),请你写一个程序求
f
(
a
,
b
)
f(a,b)
f(a,b)。
输入
第一行是一个整数 T ( 1 ≤ T ≤ 10000 ) T(1≤T≤10000) T(1≤T≤10000),表示样例的个数。 每个样例是一行,为两个整数 a , b ( 1 ≤ a ≤ b ≤ 3000000 ) a,b(1≤a≤b≤3000000) a,b(1≤a≤b≤3000000)。
输出
每行输出一个样例的结果。
样例输入
3
1 6
1 100
1 1000000
样例输出
12
3044
303963552392
提示
巨大的输入输出,请使用C风格的输入输出。
题解
既然是欧拉函数,势必要用到欧拉筛法(强烈建议各位还没学的小伙伴去学一下),关于欧拉函数的性质,百度百科上有,附上链接:欧拉函数。
简单概括如下:
①
φ
(
n
)
=
n
∗
∏
(
p
i
−
1
p
i
)
φ(n)=n*\prod(\frac{p_i -1}{p_i})
φ(n)=n∗∏(pipi−1);
②当两个数a,b互为质数,即
g
c
d
(
a
,
b
)
=
1
gcd(a,b)=1
gcd(a,b)=1时,欧拉函数
φ
(
a
∗
b
)
=
φ
(
a
)
∗
φ
(
b
)
φ(a*b)=φ(a)*φ(b)
φ(a∗b)=φ(a)∗φ(b);
③当n是质数时,有
φ
(
n
)
=
n
−
1
φ(n)=n-1
φ(n)=n−1;
下面是推导过程的截图(截至oi-wiki)
下面直接上代码
#include <stdio.h>
#define MAXLEN 3000000
int prime[220000] = { 0 };
int check[MAXLEN + 1] = { 0 };
__int64 phi[MAXLEN + 1] = { 0 };//避免累加的过程中数据溢出
int main() {
int ordNum = 1;
int i, j;
phi[1] = 1;
for (i = 2; i <= MAXLEN; i++) {
if (!check[i]) {
prime[ordNum++] = i;
phi[i] = (__int64)i - 1;//见欧拉函数性质
}
for (j = 1; j <= ordNum; j++) {
if (i * prime[j] > MAXLEN)break;
check[i * prime[j]] = 1;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
else phi[i * prime[j]] = phi[i] * phi[prime[j]];//见欧拉函数的性质
}
}
for (i = 2; i <= MAXLEN;i++) {//前缀和
phi[i] += phi[i - 1];
}
int T;
scanf_s("%d", &T);
while (T--) {
int a, b;
scanf_s("%d %d", &a, &b);
printf("%I64d\n", phi[b] - phi[a - 1]);
}
return 0;
}
另外,这道题时限较松,也可以用埃氏筛法来写,大家可以试试!有更好的解法欢迎在评论区留言!