zoukankan      html  css  js  c++  java
  • min_25筛学习笔记

    参考博客

    zsy

    xuyixuan

    litble

    前置

    min25min_25就是一种能在低于线性复杂度求积性函数f(x)f(x)前缀和的筛法

    复杂度大概为O(n34logn)O(frac{n^{frac 3 4}}{log_n})(不会证,不过朱老大论文里有证明(看不懂))

    要求f(x)f(x)是一个积性函数,而且对于素数ppf(p)f(p)f(pk)f(p^k)可以快速得到

    gg

    PP表示素数集合,MinkMin_k表示kk的最小质因子

    pripr_i表示从小到大第ii个素数

    首先考虑求出i=1n[iP]f(i)sum_{i=1}^{n}[iin P] f(i)

    定义g(n,i)=j=1n[jPorMinj>pri]f(i)g(n,i)=sum_{j=1}^{n}[jin P{or}Min_j>pr_i] f(i)

    仔细瞪一下这个函数

    我们发现从g(n,i1)g(n,i-1)g(n,i)g(n,i)

    我们就相当于做埃氏筛的过程,用pripr_i[1,n][1,n]所有还没有被筛去的pripr_i的倍数筛去

    实际上g(n,i)g(n,i)就是对[1,n][1,n]用前ii个素数做一次埃氏筛后剩下的数ff之和

    现在考虑怎么从g(n,i1)g(n,i-1)推到g(n,i)g(n,i)

    首先如果pri2>npr_{i}^2> n那显然不会有筛去任何数

    否则考虑哪些数被删去了

    一定是含质因子pip_i,而且除去pip_i后最小质因子一定大于pip_i

    考虑其实也就是减去f(pi)×g(npi,i1)f(p_i) imes g(frac n {p_i},i-1)

    又由于我们把pr1pr_1~pri1pr_{i-1}这些素数的ff值减去了,所以要再加一个j=1i1f(pj)sum_{j=1}^{i-1}f(p_j)

    所以
    g(n,i)={g(n,i1)n<pi2g(n,i1)f(pi)×[g(npi,i1)j=1i1f(pj)]pi2ng(n,i)=ni=0 g(n,i)= egin{cases} g(n,i-1) && n<p_i^2\ g(n,i-1)-f(p_i) imes[g(frac n{p_i},i-1)-sum_{j=1}^{i-1}f(p_j)] && p_i^2le n\ g(n,i)=n && i=0 end{cases}

    由于最后实际要求的是g(n,P)g(n,|P|),我们只需要开一维就可以了,第二维可以类似滚动数组滚掉

    又由于大于nsqrt n的质因子只有一个

    所以我们可以记f1[i]f1[i]表示g(i,j)g(i,j)f2[i]f2[i]表示g(ni,j)g(frac n i,j)

    这样空间复杂度只有O(n)O(sqrt n)

    代码:当f(p)=1f(p)=1即求素数个数时
    代码实现比较精细
    可以证明这样复杂度是O(n34logn)O(frac{n^{frac 3 4}}{log_n})

    int lim=sqrt(n);
    for(int i=1;i<=lim;i++)f1[i]=i-1,f2[i]=n/i-1;
    for(int p=2;p<=lim;p++){
    	if(f1[p]==f1[p-1])continue;
    	for(int i=1;i<=lim/p;i++)f2[i]-=f2[i*p]-f1[p-1];
    	for(int i=lim/p+1;1ll*i*p*p<=n&&i<=lim;i++)f2[i]-=f1[n/i/p]-f1[p-1];
    	for(int i=lim;i>=1ll*p*p;i--)f1[i]-=f1[i/p]-f1[p-1];
    }
    return f2[1];
    

    但是会跑的很慢
    你找一照发现问题很简单
    卡一下数组枚举和除法以及一些常用变量就会快565、6

    lim=sqrt(n);
    for(i=1;i<=lim;++i)f1[i]=i-1,f2[i]=n/i-1,inv[i]=1.0/i;
    for(p=2;p<=lim;++p){
    	if(f1[p]==f1[p-1])continue;
    	x0=f1[p-1],w1=lim/p,w2=min(lim,(n/p/p)),dd=n/p;
    	for(i=1;i<=w1;++i)f2[i]+=x0-f2[i*p];
    	for(i=lim/p+1;i<=w2;++i)f2[i]+=x0-f1[(int)(inv[i]*dd+1e-7)];
    	for(i=lim;i>=1ll*p*p;--i)f1[i]+=x0-f1[(int)(inv[p]*i+1e-7)];
    }
    return f2[1];
    

    SS

    现在我们已经求出了i=1n[iP]f(i)sum_{i=1}^{n}[iin P] f(i)

    考虑如何计算合数的答案

    S(n,i)=j=1n[Minjpri]f(j)S(n,i)=sum_{j=1}^n [Min_jgeq pr_i] f(j)

    即满足所有质因子大于等于pip_i的数的ff之和

    那么显然i=1nf(i)=S(n,1)+f(1)sum_{i=1}^{n} f(i)=S(n,1)+f(1)
    考虑如何类似的递推

    首先素数的答案已经算出来了
    显然的是g(n,P)j=1i1f(prj)g(n,|P|)-sum_{j=1}^{i-1}f(pr_j)(因为SS要求MinjpriMin_jge pr_i)

    考虑枚举合数的最小质因子和次数,直接算就是了

    S(n,i)=g(n,P)j=1i1f(prj)+j=iprj2nxs=1prjxs+1nS(nprjxs,j+1)×f(prjxs)+f(prjxs+1)S(n,i)=g(n,|P|)-sum_{j=1}^{i-1}f(pr_j)+sum_{j=i}^{pr_j^2le n}sum_{xs=1}^{pr_j^{xs+1}le n}S(frac{n}{pr_j^{xs}},j+1) imes f(pr_j^{xs})+f(pr_j^{xs+1})

    好像这样的复杂度是n1ϵlognfrac{n^{1-epsilon}}{logn}
    不过跑的还比较快

    然后就没了
    代码看例题里的就可以了

    例题:

    LOJ6235LOJ6235

    LOJ6202LOJ6202

    LOJ6053LOJ6053

    UOJ188UOJ188

    BZOJ5244BZOJ5244

    SPOJDIVCNTKSPOJ-DIVCNTK

  • 相关阅读:
    进程的描述
    前驱图和程序执行
    图形化编程娱乐于教,Kittenblock实例,小瓢虫找妈妈
    图形化编程娱乐于教,Kittenblock实例,猫抓老鼠使用扑鼠器
    图形化编程娱乐于教,Kittenblock实例,键盘控制猫抓老鼠
    图形化编程娱乐于教,Kittenblock实例,鼠标控猫抓老鼠
    图形化编程娱乐于教,Kittenblock实例,随机数猜测押宝
    图形化编程娱乐于教,Kittenblock实例,按钮控制动画
    图形化编程娱乐于教,Kittenblock实例,甲虫画出蜈蚣效果
    图形化编程娱乐于教,Kittenblock实例,图章的艺术
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328739.html
Copyright © 2011-2022 走看看