zoukankan      html  css  js  c++  java
  • [学习笔记]Min_25筛

    注意到我们做反演题时,并不需要用到前缀和中的所有信息,大多数时候只需要用到(lfloorfrac n 1 floor,lfloorfrac n 2 floor,lfloorfrac n 3 floor......)这几项即可,而今天我们要讲的Min_25筛,就是专门为求出这些位置的前缀和而生的。

    既然要求的项数少了,时间复杂度自然也就少了,Min_25的时间复杂度是(varTheta(frac {n^{frac 3 4}}{ln(n)}))的。

    大体思路

    • Min_25筛在处理时把质数分为大于(sqrt n)与小于(sqrt n)两个部分。

    注意到大于(sqrt n)的部分,在计算对于x的贡献时,只会是1次方的,所以我们可以先求出它们对于各前缀和的贡献,而对于小于(sqrt n)的部分,我们则暴力枚举每个质数的次方数即可。

    具体实现

    这里以求(varphi)的前缀和为例。

    第一部分

    • 第一部分:大于(sqrt n)的质数(不妨叫它们大质数)的贡献

    因为最后每个大质数只会以1次的形式出现,所以我们只需求出((p_i-1))即可。(下面我们将它们分为1次与0次两部分求解)

    • (f[i][j])表示:(2)~(j)中小于等于(p_i)的质数的数值(我们称其为第一坨),与最小质因子大于(p_i)的数的数值的和(第二坨)。((iin [0,sqrt n]))

    这里,我们的想法是通过把小质数的贡献删光,从而只留下大质数,所以i的枚举到(sqrt n)为止。

    先是1次的部分。

    显然有初始条件:(f[0][j]=frac{j imes(j+1)}{2})

    • 考虑转移:

    (egin{aligned}f[i+1][j]=f[i][j]-(f[i][lfloorfrac j {p_{i+1}} floor]-sum_{k=1}^ik) imes p_{i+1}end{aligned})

    • 来解释一下这个式子:

    我们需要筛掉那些最小质因子为(p_{i+1})的数的贡献,也就是dp式中的第二坨,而这就是括号中的部分。括号中后面的(sum) 是为了删去了dp式中的第一坨。(因为质数(p_{i+1})本就在答案中,只要不把它筛掉即可,不需要再在后面另外加)

    • 0次的部分处理类似,这里只给出式子:

    (egin{aligned}f'[i+1][j]=f'[i][j]-(f'[i][lfloorfrac{j}{p_{i+1}} floor]-sum_{k=1}^ii) imes1end{aligned})

    最后我们将(f)(f')相加,得到(F),那么(F[sqrt n][k])即是小于等于(k)的所有质数的贡献。

    第二部分

    第二部分:小质数的贡献

    • (g[i][j])表示:(2)~(j)中小于等于(p_i)的质数的(varphi)值(我们称其为第一坨),与最小质因子大于(p_i)的数的(varphi)的和(第二坨)。((iin [0,sqrt n]))

    有初始条件:(g[k][j]=F[k][j],kin[1,sqrt n])

    我们刚刚把合数都筛光了,那么现在就要把它们给加回来。

    • 我们枚举每一个小质数质数的次数,考虑转移:

    (egin{aligned}g[i-1][j]=g[i][j]+sum_{p_i^{e+1}le j}[(g[i][lfloorfrac{j}{p_{i}^e} floor]-sum_{k=1}^ivarphi(p_k)) imes varphi(p_i^e)+varphi(p_i^{e+1})]end{aligned})

    • 解释一下式子:

    因为p每多1次,对于答案的影响都不一样(第一次是乘p-1,后来是乘p),所以我们需要枚举次数,求出每一个(p^e)对于答案的贡献。大体思路和之前的相似,只是因为这次我们是要往里面加,所以需要在后面挂上(p^{e+1})的贡献。

    一些细节

    第一部分时从小到大枚举i,第二部分从大到小枚举i。

    为了在内存上去掉i这一维,我们需要从大到小枚举j。

    因为我们只需要求(lfloorfrac n 1 floor,lfloorfrac n 2 floor,......),而且在转移时也只会用到这几项,所以我们只需要把这(sqrt n)项标个号即可,这样就把j这一维也降到了(sqrt n),在空间上绝对是妥妥的。

    只有当时(lfloorfrac n k floor>p_i)才进行转移,不然的话一减后面那坨(sum)必定等于0。((*))

    显然,括号中的那坨(sum)能预处理。

    • 关于时间复杂度:

    有了“优化((*))”,我们就能把原先看上去是(varTheta(frac{n}{ln(n)}))的算法变成(varTheta(frac{n^{frac 3 4}}{ln(n)})),但是我太菜了,并不会具体的证明。。。。


    • 洛谷模板题的代码:
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=1e6+5,mod=1e9+7;
    const ll inv6=166666668%mod;
    int vis[maxn],p[maxn],id1[maxn],id2[maxn],tot;
    ll sum1[maxn],sum2[maxn],f[maxn],g1[maxn],g2[maxn],to[maxn],n,sqrtn,tt;
    void sieve(int N){
    	vis[1]=1;
    	for (int i=2;i<=N;i++){
    		if (!vis[i]) p[++p[0]]=i,sum1[p[0]]=(sum1[p[0]-1]+i)%mod,sum2[p[0]]=(sum2[p[0]-1]+1ll*i*i%mod)%mod;
    		for (int j=1;j<=p[0]&&i*p[j]<=N;j++){
    			vis[i*p[j]]=1;
    			if (i%p[j]==0) break;
    		}
    	}
    }
    int getid(ll x) {return x<=sqrtn?id1[x]:id2[n/x];}
    ll Mod(ll x) {return (x%mod+mod)%mod;}
    int main(){
    	scanf("%lld",&n);
    	sieve(sqrtn=sqrt(n));
    	for (ll l=1,r;l<=n;l=r+1){
    		r=n/(n/l);
    		ll w=n/l;
    		to[++tot]=w;
    		if (w<=sqrtn) id1[w]=tot; else id2[n/w]=tot;
    		w%=mod;
    		g1[tot]=w*(w+1)/2%mod;
    		g2[tot]=w*(w+1)%mod*(2ll*w+1)%mod*inv6%mod;
    		g1[tot]=(g1[tot]-1+mod)%mod;
    		g2[tot]=(g2[tot]-1+mod)%mod;
    	}
    	for (int i=1;i<=p[0];i++)
    		for (int j=1;j<=tot&&to[j]>=1ll*p[i]*p[i];j++){
    			int k=getid(to[j]/p[i]);
    			g1[j]=(g1[j]-Mod(g1[k]-sum1[i-1])*p[i]%mod+mod)%mod;
    			g2[j]=(g2[j]-Mod(g2[k]-sum2[i-1])*p[i]%mod*p[i]%mod+mod)%mod;
    		}
    	for (int i=1;i<=tot;i++) f[i]=Mod(g2[i]-g1[i]);
    	for (int i=p[0];i>=1;i--)
    		for (int j=1;j<=tot&&to[j]>=1ll*p[i]*p[i];j++)
    			for (ll t=p[i];t*p[i]<=to[j];t*=p[i]){
    				int k=getid(to[j]/t);
    				tt=t%mod;
    				f[j]=(f[j]+Mod(f[k]-sum2[i]+sum1[i])*tt%mod*Mod(tt-1)%mod+tt*p[i]%mod*Mod(tt*p[i]%mod-1)%mod)%mod;
    			}
    	printf("%lld
    ",(f[1]+1)%mod);
    	return 0;
    }
    
    
  • 相关阅读:
    JAVA微信公众号网页开发——获取公众号关注的所有用户
    删除mysl
    sql语言(mysql)
    mycat读写分离
    mysql双主双从技术
    实用的10个日志处理案例
    ansible基本操作
    MySQL改密
    mysql源码包安装
    ftp搭建mysql服务器
  • 原文地址:https://www.cnblogs.com/WR-Eternity/p/13732451.html
Copyright © 2011-2022 走看看