今天给大家讲解GCD这个题目
题目描述
我们定义
f
(
x
)
=
g
c
d
(
f(x)=gcd(
f(x)=gcd(
x
x
x除
1
1
1以外的所有因子
)
)
)
询问从
f
(
a
)
+
f
(
a
+
1
)
+
.
.
.
.
.
.
+
f
(
b
)
f(a)+f(a+1)+......+f(b)
f(a)+f(a+1)+......+f(b)
输入格式
输入两个正整数 a b
输出格式
输出一个正整数表示答案
样例
样例输入
5 7
样例输出
13
数据范围与提示
对于 100% 的数据,
1
<
a
<
b
<
1<a<b<
1<a<b< 107
思路
牛客网的这场比赛我没有打,是赛后老师布置给我们的素数筛练习题。
我们先不看
f
(
a
)
+
f
(
a
+
1
)
+
.
.
.
.
.
.
+
f
(
b
)
f(a)+f(a+1)+......+f(b)
f(a)+f(a+1)+......+f(b)具体的值是多少,我们只单独分析
f
(
x
)
f(x)
f(x)本身,且我们设
a
n
s
ans
ans为最终答案。
情况一:
x
x
x为质数
很显然,如果
x
x
x为质数则
x
x
x除一以外的因子就只有
x
x
x他本身,所以
a
n
s
+
=
x
ans+=x
ans+=x。
情况二:
x
x
x为一个质数
y
y
y的整数次方
为什么我们要讨论这种情况呢?因为当且仅当在这种情况下,
x
x
x除去1以外的所有因子的
g
c
d
gcd
gcd一定是这个素数
y
y
y。所以最终答案
a
n
s
+
=
y
ans+=y
ans+=y。
情况三:
x
x
x非质数,也非一个质数的整数次方
这种情况下,没有什么可以讨论的,
a
n
s
+
=
1
ans+=1
ans+=1。
讨论完了怎么处理
f
(
x
)
f(x)
f(x)之后,就是要看怎么实现了。
至于怎么判断质数嘛,比较简单,直接运用我们以前学过的欧拉筛进行筛选。
至于怎么判断他是一个质数的整数次方也比较简单,我们在开始输入之前,将所有是质数平方的数字全部打上标记即可。
代码
#include<bits/stdc++.h>
using namespace std;
bool st[10000001];
int primes[1000000];
int n,cnt=0,i,j;
int p[10000005];
//欧拉筛
void ola(int n)
{
st[1]=0;
for(i=2;i<=n;i++)
{
if(st[i])
primes[cnt++]=i;
for(j=0;primes[j]*i<=n&&j<=cnt;j++)
{
st[primes[j]*i]=0;
if(i%primes[j]==0)
break;
}
}
}
//处理所有是质数整数次方的数
void func(int o)
{
memset(p,0x3f,sizeof(p));
for(int i=2;i<=sqrt(o);++i)
{
if(st[i]==0)
continue;
for(int j=2;pow(i,j)<=o;++j)
{
int e=pow(i,j);
p[e]=min(p[e],i);
}
}
for(int i=1;i<=o;++i)
{
if(p[i]==0x3f3f3f3f)
p[i]=1;
}
}
int main()
{
memset(st,1,sizeof(st));
int l,r;
long long ans=0;
scanf("%d%d",&l,&r);//输入
//直接调用函数
ola(r);func(r);
for(int i=l;i<=r;++i)
{
if(st[i]==1)//判断是否是质数
ans+=i;
else
ans+=p[i];
}
cout<<ans;//输出
return 0;
}