今天给大家讲解GCD这个题目
题目描述
我们定义f(x)=gcd(f(x)=gcd(f(x)=gcd(xxx除111以外的所有因子)))
询问从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)本身,且我们设ansansans为最终答案。
情况一:xxx为质数
很显然,如果xxx为质数则xxx除一以外的因子就只有xxx他本身,所以ans+=xans+=xans+=x。
情况二:xxx为一个质数yyy的整数次方
为什么我们要讨论这种情况呢?因为当且仅当在这种情况下,xxx除去1以外的所有因子的gcdgcdgcd一定是这个素数yyy。所以最终答案ans+=yans+=yans+=y。
情况三:xxx非质数,也非一个质数的整数次方
这种情况下,没有什么可以讨论的,ans+=1ans+=1ans+=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;
}

287





