【UOJ188】 Sanrd【类min_25筛】

题意:设 f ( i ) f(i) f(i)表示 i i i的不严格次大质因子(没有为 0 0 0),求 ∑ i = l r f ( i ) \sum_{i=l}^rf(i) i=lrf(i)

l ≤ r ≤ 1 0 11 l\leq r\leq10^{11} lr1011

这种和质因数有关的奇奇怪怪的函数的前缀和可以试试魔改min_25筛

S ( n , j ) = ∑ i = 2 n [ m i n p ( i ) > p j ] f ( i ) S(n,j)=\sum_{i=2}^n[minp(i)>p_j]f(i) S(n,j)=i=2n[minp(i)>pj]f(i)

枚举最小的质因子 p k p_k pk以及次数 e e e

如果 p k p_k pk不是次大质因子,直接递归到 S ( ⌊ n p k e ⌋ , k ) S(\lfloor\frac{n}{p_k^e}\rfloor,k) S(pken,k)

否则考虑 p k p_k pk的贡献

如果是严格次大,那么枚举最大的质因子

否则就是 [ e > 1 ] [e>1] [e>1]

S ( n , j ) = ∑ k = j + 1 p k ≤ n ∑ e = 1 p k e ≤ n ( S ( ⌊ n p k e ⌋ , k ) + ∑ i = p k + 1 ⌊ n p k e ⌋ [ i ∈ p r i m e ] + [ e > 1 ] ) S(n,j)=\sum_{k=j+1}^{p_k\leq\sqrt n}\sum_{e=1}^{p_k^e\leq n}(S(\lfloor\frac{n}{p_k^e}\rfloor,k)+\sum_{i=p_k+1}^{\lfloor\frac{n}{p_k^e}\rfloor}[i\in prime]+[e>1]) S(n,j)=k=j+1pkn e=1pken(S(pken,k)+i=pk+1pken[iprime]+[e>1])

注意 p k + 1 p_k+1 pk+1可能大于 ⌊ n p k e ⌋ \lfloor\frac{n}{p_k^e}\rfloor pken,要特判一下

然后用min_25的方法预处理出质数个数的前缀和即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#define MAXN 1000005
using namespace std;
const int N=1e6;
int np[MAXN],pl[MAXN],cnt;
void init()
{
	np[1]=1;
	for (int i=2;i<=N;i++)
	{
		if (!np[i]) pl[++cnt]=i;
		for (int j=1,x;(x=i*pl[j])<=N;j++)
		{
			np[x]=1;
			if (i%pl[j]==0) break;
		}
	}
}
typedef long long ll;
ll val[MAXN],n,m;
int key[MAXN],yek[MAXN],tot;
inline int getkey(ll x){return x<=m? key[x]:yek[n/x];}
ll g[MAXN];
ll S(ll n,int j)
{
	if ((ll)pl[j]*pl[j]>n) return 0;
	ll sum=0;
	for (int k=j+1;(ll)pl[k]*pl[k]<=n&&k<=cnt;k++)
		for (ll e=1,v=pl[k];v<=n;e++,v*=pl[k])
			sum+=S(n/v,k)+pl[k]*(max(0ll,g[getkey(n/v)]-k)+(e>1));
	return sum;
}
ll solve(ll N)
{
	m=sqrt(n=N);
	tot=0;
	for (ll l=1,r;l<=n;l=r+1)
	{
		r=n/(n/l);
		val[++tot]=n/l;
		if (val[tot]<=m) key[val[tot]]=tot;
		else yek[n/val[tot]]=tot;
	}
	for (int i=1;i<=tot;i++) g[i]=val[i]-1;
	for (int j=1;j<=cnt;j++)
		for (int i=1;(ll)pl[j]*pl[j]<=val[i];i++)
			g[i]-=g[getkey(val[i]/pl[j])]-j+1;
	return S(n,0);
}
int main()
{
	init();
	ll l,r;
	cin>>l>>r;
	cout<<solve(r)-solve(l-1);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值