Description
这里是跳蚤国中央广播电台,现在为您转播的是著名人类智慧大师pickspicks博士与人工智能betacomebetacome之间的最后一轮赛事。
这一场交锋的规则由网友st∗∗∗∗llst∗∗∗∗ll提供,这位网友也将获得由不想跳的跳蚤不是好跳蚤——最强跳蚤跳跳跳公司提供的金牌跳蚤一只。
就在刚才,第二轮比赛也已经结束了,pickspicks博士不负众望为人类扳回了一城。特别是在刚才劣势的时候,pickspicks博士突然地停止了对盘子的操作,让betacomebetacome乱了阵脚,并最后实现了反超,这一手操作也被网友戏称为“神之一手”。
“恩,这一手表明了betacomebetacome也是存在弱点而不是不可战胜的,pickspicks博士可能也在一直尝试着不同的比赛风格,试图找到betacomebetacome的漏洞。上一场的胜利说明了betacomebetacome在对于突发事件的应对方式可能存在着缺陷,在这一轮pickspicks博士应该会针对这一点进行比赛,我认为他的胜率应该会非常大。”
那看来AA先生抱着非常乐观的心态啊,现在最后一轮的比赛已经开始了,同样,接下来由先生来给我们介绍一下这一轮比赛的规则。
“好,大家现在看屏幕,在这一轮游戏中,给出了一个如下所示的将nn分解质因子的算法。”
- 检查是否是质数,假如nn是质数或则直接结束。
- 定义一个变量pp,初始值为。
- 检查pp是否是的因子,假如pp是的因子,不断将nn除去,直到pp不再是的质因子。
- 检查nn是否是质数,假如是质数或n=1n=1,就结束这个算法,否则将pp的值加一,返回第三步。
“为了检验人类智慧和人工智能之间的计算能力的差距,主办方希望选手对区间 中的所有数都用这个算法进行分解。为了检验计算的正确性,选手需要计算分解完每一个数后,pp的和。特殊地,如果分解在第一步就结束了,那么就认为。”
恩,谢谢AA先生。大家可以看到这一道是数论方面的题目,刚才AA先生也私下和我说了,这一道题目的难度要比前两轮的难度高很多,他认为在短时间内,比赛双方都无法得到准确的结果。因为我们节目组决定与观众们进行互动,正在收看节目的观众可以关注节目跳蚤信公众号参与解题,最快得到正确答案的观众将会获得由不想跳的跳蚤不是好跳蚤——最强跳蚤跳跳跳公司提供的精美礼品一份。
作为一名光荣的吃土少年,你立志要把这份礼品收入囊中以告别悲惨的吃土生活。然而,全世界的观众中也不乏人类智慧大师的存在,为了从他们中脱颖而出,你需要以最快的速度得到这一个问题的答案。
Input
一行两个正整数,表示需要分解的数的范围(1≤l≤r≤1011)(1≤l≤r≤1011)
Output
输出一行一个整数,表示每次分解结束时,变量pp的值之和。
Sample Input
16 20
Sample Output
7
Solution
设为分解nn结束时的值,若nn为或素数则有f(p)=0f(p)=0,否则f(n)f(n)即为nn的次大素因子
假设的取值分别为val1,...,valcntval1,...,valcnt,n−−√n以内的素数为p1,...,pmp1,...,pm,设S(i,j)S(i,j)为[1,vali][1,vali]中最小素因子不小于pjpj的数字的ff值之和,显然其中的素数没有贡献,对于其中的合数,枚举起最小素因子以及其幂指数ee,那么数字有两种:,其中n′n′为最小素因子大于pkpk的合数,第一种对答案的贡献为pkpk,第二种对答案的贡献为n′n′对答案的贡献,进而有转移
用min_25min_25筛求出g(i)g(i)表示[1,vali][1,vali]中素数个数,那么最后一个求和即为g(i)−(k−1)g(i)−(k−1)
Code
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
#define maxn 700005
int p[maxn],f[maxn],np=0,m=350000;
void get_prime(int n)
{
for(int i=2;i<=n;i++)
{
if(!f[i])p[++np]=i;
for(int j=1;j<=np&&i*p[j]<=n;j++)
{
f[i*p[j]]=1;
if(i%p[j]==0)break;
}
}
np--;
}
ll val[maxn],n;
int nn,cnt;
void init()
{
nn=1;
while((ll)nn*nn<n)nn++;
cnt=0;
for(ll i=1;i<=n;i=n/(n/i)+1)val[++cnt]=n/i;
}
int ID(ll x)
{
if(x>=nn)return n/x;
return cnt-x+1;
}
ll g0[maxn];
void Get_g(ll n)
{
for(int i=1;i<=cnt;i++)g0[i]=val[i]-1;
for(int j=1;j<=np;j++)
for(int i=1;i<=cnt&&(ll)p[j]*p[j]<=val[i];i++)
{
int k=ID(val[i]/p[j]);
g0[i]=g0[i]-(g0[k]-(j-1));
}
return ;
}
ll S(ll i,int j)
{
if(i<=1||p[j]>i)return 0;
int k=ID(i);
ll ans=0;
for(int k=j;k<=np&&(ll)p[k]*p[k]<=i;k++)
{
ll p1=p[k],p2=(ll)p[k]*p[k];
for(int e=1;p2<=i;p1=p2,p2*=p[k],e++)
ans+=S(i/p1,k+1)+(g0[ID(i/p1)]-k+1)*p[k];
}
return ans;
}
int main()
{
get_prime(m);
scanf("%lld",&n);
n--;
init();
Get_g(n);
ll ans=-S(n,1);
scanf("%lld",&n);
init();
Get_g(n);
ans+=S(n,1);
printf("%lld\n",ans);
return 0;
}