GCD \operatorname{GCD} GCD
题目链接: nowcoder 211962 \operatorname{nowcoder\ 211962} nowcoder 211962
到牛客看:
题目
我们定义
f
(
x
)
=
gcd
(
x
\text{f}(x) = \text{gcd}(x
f(x)=gcd(x 除
1
1
1 之外的所有因子
)
)
)
即
x
x
x 除
1
1
1 外所有因子的
gcd
\text{gcd}
gcd
询问从
f
(
a
)
+
f
(
a
+
1
)
+
…
…
+
f
(
b
)
\text{f}(a) + \text{f}(a+1) + …… + \text{f}(b)
f(a)+f(a+1)+……+f(b)
输入
输入两个正整数 a , b a,b a,b
输出
输出一个正整数表示答案
样例输入
5 7
样例输出
13
数据范围
对于
20
%
20\%
20% 的数据,
1
<
a
<
b
<
=
1000
1 < a < b <= 1000
1<a<b<=1000
对于
40
%
40\%
40% 的数据,
1
<
a
<
b
<
=
1
0
6
1 < a < b <= 10^6
1<a<b<=106
对于
100
%
100\%
100% 的数据,
1
<
a
<
b
<
=
1
0
7
1<a<b<=10^7
1<a<b<=107
思路
这道题是一道数学题。
题目的 f \text{f} f 函数要的是一个数所有除了 1 1 1 的因子的 gcd \text{gcd} gcd。
我们大概想想就会发现,如果这一个数分解质因数可以分解出不止一种质数,那的出来的
f
\text{f}
f 函数值就是
1
1
1。
(因为这个数至少会有这两个质数为因子,而两个质数的
gcd
\text{gcd}
gcd 又是一,那的出来就只能是
1
1
1 了)
那我们就先素数筛选法找出
b
b
b 以内的质数,然后对于每一个质数,就枚举多少个这个质数乘在一起,对于每一个数,它对答案的贡献就是那个质数。
最后还没有对答案产生贡献的数,就是由不止一个质数乘起来得到的数,对答案的贡献就是
1
1
1。
( 1 1 1 的话就是对答案贡献 1 1 1,所以可以算在由不止一个质数乘起来得到的数里面)
代码
#include<cstdio>
using namespace std;
long long a, b, ans, susu[10000024], tot;
bool yes[10000024];
int main() {
scanf("%lld%lld",&a,&b);
for(long long i = 2; i <= b; i++) {
if(!yes[i]) susu[tot++] = i;
for(long long j = 0; j < tot && i * susu[j] <= b; j++)
yes[i * susu[j]] = 1;
}
ans = b - a + 1;//先假设全部贡献都是 1
for(long long i = 0; i < tot; i++)
for(long long j = susu[i]; j <= b; j *= susu[i])
if(a <= j) ans += susu[i] - 1;//是质数的贡献,就让贡献加上质数减去之前加上的 1
printf("%lld", ans);
return 0;
}