UOJ 188 [UR #13]Sanrd(min_25筛)

2 篇文章 0 订阅

Description

这里是跳蚤国中央广播电台,现在为您转播的是著名人类智慧大师 picks p i c k s 博士与人工智能 betacome b e t a c o m e 之间的最后一轮赛事。

这一场交锋的规则由网友 stll s t ∗ ∗ ∗ ∗ l l 提供,这位网友也将获得由不想跳的跳蚤不是好跳蚤——最强跳蚤跳跳跳公司提供的金牌跳蚤一只。

就在刚才,第二轮比赛也已经结束了, picks p i c k s 博士不负众望为人类扳回了一城。特别是在刚才劣势的时候, picks p i c k s 博士突然地停止了对盘子的操作,让 betacome b e t a c o m e 乱了阵脚,并最后实现了反超,这一手操作也被网友戏称为“神之一手”。

“恩,这一手表明了 betacome b e t a c o m e 也是存在弱点而不是不可战胜的, picks p i c k s 博士可能也在一直尝试着不同的比赛风格,试图找到 betacome b e t a c o m e 的漏洞。上一场的胜利说明了 betacome b e t a c o m e 在对于突发事件的应对方式可能存在着缺陷,在这一轮 picks p i c k s 博士应该会针对这一点进行比赛,我认为他的胜率应该会非常大。”

那看来 A A 先生抱着非常乐观的心态啊,现在最后一轮的比赛已经开始了,同样,接下来由A先生来给我们介绍一下这一轮比赛的规则。

“好,大家现在看屏幕,在这一轮游戏中,给出了一个如下所示的将 n n 分解质因子的算法。”

  1. 检查n是否是质数,假如 n n 是质数或n=1则直接结束。

    • 定义一个变量 p p ,初始值为2
    • 检查 p p 是否是n的因子,假如 p p n的因子,不断将 n n 除去p,直到 p p 不再是n的质因子。
    • 检查 n n 是否是质数,假如n是质数或 n=1 n = 1 ,就结束这个算法,否则将 p p 的值加一,返回第三步。

“为了检验人类智慧和人工智能之间的计算能力的差距,主办方希望选手对区间[l,r] 中的所有数都用这个算法进行分解。为了检验计算的正确性,选手需要计算分解完每一个数后, p p 的和。特殊地,如果分解在第一步就结束了,那么就认为p=0。”

恩,谢谢 A A 先生。大家可以看到这一道是数论方面的题目,刚才 A A 先生也私下和我说了,这一道题目的难度要比前两轮的难度高很多,他认为在短时间内,比赛双方都无法得到准确的结果。因为我们节目组决定与观众们进行互动,正在收看节目的观众可以关注节目跳蚤信公众号参与解题,最快得到正确答案的观众将会获得由不想跳的跳蚤不是好跳蚤——最强跳蚤跳跳跳公司提供的精美礼品一份。

作为一名光荣的吃土少年,你立志要把这份礼品收入囊中以告别悲惨的吃土生活。然而,全世界的观众中也不乏人类智慧大师的存在,为了从他们中脱颖而出,你需要以最快的速度得到这一个问题的答案。

Input

一行两个正整数l,r,表示需要分解的数的范围 (1lr1011) ( 1 ≤ l ≤ r ≤ 10 11 )

Output

输出一行一个整数,表示每次分解结束时,变量 p p 的值之和。

Sample Input

16 20

Sample Output

7

Solution

f(n)为分解 n n 结束时的p值,若 n n 1或素数则有 f(p)=0 f ( p ) = 0 ,否则 f(n) f ( n ) 即为 n n 的次大素因子

假设ni的取值分别为 val1,...,valcnt v a l 1 , . . . , v a l c n t n n 以内的素数为 p1,...,pm p 1 , . . . , p m ,设 S(i,j) S ( i , j ) [1,vali] [ 1 , v a l i ] 中最小素因子不小于 pj p j 的数字的 f f 值之和,显然其中的素数没有贡献,对于其中的合数,枚举起最小素因子pk以及其幂指数 e e ,那么数字有两种:pkepl(lk)pken,其中 n n ′ 为最小素因子大于 pk p k 的合数,第一种对答案的贡献为 pk p k ,第二种对答案的贡献为 n n ′ 对答案的贡献,进而有转移

S(i,j)=kjpe+1kvali(S(valipek,k+1)+pkp=pkvali[p]) S ( i , j ) = ∑ k ≥ j ∑ p k e + 1 ≤ v a l i ( S ( ⌊ v a l i p k e ⌋ , k + 1 ) + p k ∑ p = p k v a l i [ p 是 素 数 ] )

min_25 m i n _ 25 筛求出 g(i) g ( i ) 表示 [1,vali] [ 1 , v a l i ] 中素数个数,那么最后一个求和即为 g(i)(k1) 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值