uoj#188. 【UR #13】Sanrd(Min_25筛)

题面

传送门

题解

这是一道语文题

不难看出,题目所求即为\(l\)\(r\)中每个数的次大质因子

我们考虑\(Min\_25\)筛的过程,设

\[S(n,j)=\sum_{i=1}^nsec_p(i)[min_p(i)\geq P_j] \]

用人话来说的话,就是\(S(n,j)\)表示\(1\)\(n\)之间所有满足最小值因子大于等于\(P_j\)\(i\)的次大质因子之和

我们照例把质数和合数的贡献分开考虑。所有质数贡献为\(0\),而对于合数,我们枚举最小质因子\(P_k\)。此时分为两种情况,如果\(P_k\)不是次大质因子,那么\(S(n,j)\)要加上所有满足\(k>j\)\(S(\left\lfloor\frac{n}{{P_k}^e}\right\rfloor,k+1)\)。如果\(P_k\)是次大质因子,那么剩下的数肯定是一个大于等于\(P_k\)的质因子,也就是\(P_k\)\(\left\lfloor\frac{n}{{P_k}^e}\right\rfloor\)之间质数的个数

用从隔壁大佬那里偷来的公式来写的话就是这样子

\[S(n,j)=\sum_{k\ge j}\sum_{e=1}^{p_k^{e+1}\le n}S(\lfloor\frac{n}{p^{e}_k}\rfloor,k+1)+p_k\sum_{i=p_k}^{\lfloor\frac{n}{p^{e}_k}\rfloor}[i\in P] \]

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
const int N=1e6+5;
int p[N],id1[N],id2[N],m,tot,sqr;bitset<N>vis;
ll l,r,qwq,w[N],g[N];
void init(int n){
	fp(i,2,n){
		if(!vis[i])p[++tot]=i;
		for(R int j=1;j<=tot&&1ll*i*p[j]<=n;++j){
			vis[i*p[j]]=1;
			if(i%p[j]==0)break;
		}
	}
}
ll S(ll n,int m){
	if(n<=2||p[m]>n)return 0;
	ll res=0;
	for(R int i=m;i<=tot&&1ll*p[i]*p[i]<=n;++i)
		for(R ll tmp=p[i];tmp*p[i]<=n;tmp*=p[i]){
			int k=(n/tmp<=sqr)?id1[n/tmp]:id2[qwq/(n/tmp)];
			res+=S(n/tmp,i+1)+(g[k]-i+1)*p[i];
		}
	return res;
}
ll calc(ll n){
	qwq=n,m=0;
	for(R ll i=1,j;i<=n;i=j+1){
		j=n/(n/i),w[++m]=n/i;
		w[m]<=sqr?id1[w[m]]=m:id2[n/w[m]]=m;
		g[m]=w[m]-1;
	}
	fp(j,1,tot)for(R int i=1;1ll*p[j]*p[j]<=w[i];++i){
		int k=(w[i]/p[j]<=sqr)?id1[w[i]/p[j]]:id2[n/(w[i]/p[j])];
		g[i]=g[i]-g[k]+j-1;
	}
	return S(n,1);
}
int main(){
//	freopen("testdata.in","r",stdin);
	scanf("%lld%lld",&l,&r),init(sqr=sqrt(r));
	printf("%lld\n",calc(r)-calc(l-1));
	return 0;
}
posted @ 2019-02-21 21:30  bztMinamoto  阅读(272)  评论(0编辑  收藏  举报
Live2D