UOJ #188. 【UR #13】Sanrd (Min_25筛的广义应用)

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/88311573

题目
我琢磨着我怎么越来越会写标题了呢?
这个题很明显不是积性函数。
就像:51nod 1847 奇怪的数学题-对次小质因数下功夫。
而这个题是让我们求次大质因数。
考虑Min_25筛第二部分求答案的过程。
S(a,b)表示2~a中 m i n p r i m e > = p r i m e b minprime >= prime_b 的答案。
那么S(a,b)可以通过(套路)枚举质数和质数的次方,如果当前质数要当作次大质因数, S ( a , b ) + = p r i p r b a p r i k S(a,b) += pr_i * 在pr_b和{\frac a{pr_i^k}}之间的质数数量 ,如果不作,那就简单的 S ( a , b ) + = S ( a p r i , b + 1 ) S(a,b) += S(\frac a{pr_i},b+1)
这个。。。由此我们推出结论,和所包含质数有关系的题,可以使用类Min_25的dp顺序记忆化搜索。
我们不妨叫这:基于枚举最小质因子的状态整除分块压缩DP

AC Code:

#include<bits/stdc++.h>
#define maxn 700005
#define LL long long
using namespace std;

LL n,s0[maxn],a[maxn],sm0[maxn],pr[maxn],cnt_pr;
int sqt,cnt;
inline int id(LL x){ return x<=sqt?x:cnt-n/x+1; }

LL S(LL a,LL b)
{
	if(a < pr[b]) return 0;
	int pos = id(a);
	LL ret = 0;
	for(int i=b;i<=cnt_pr&&pr[i]*pr[i]<=a;i++)
		for(LL x=pr[i],lim=a/pr[i];x<=lim;x*=pr[i])
			ret += S(a/x,i+1) + pr[i]*(s0[id(a/x)]-i+1);
	return ret;
}

LL Solve(LL num)
{
	n = num;
	sqt = sqrt(num);
	cnt = cnt_pr = 0;
	for(LL i=1;i<=n;i++)
		a[++cnt] = i = n/(n/i),
		s0[cnt] = i-1;
	for(LL i=1;i<=sqt;i++)
		if(s0[i]!=s0[i-1])
		{
			pr[++cnt_pr] = i;
			sm0[cnt_pr] = sm0[cnt_pr-1] + 1;
			for(LL j = cnt , lim = i * i; a[j] >= lim ; j--)
				s0[j] -= s0[id(a[j]/i)] - sm0[cnt_pr-1];
		}
		
	return S(n,1);
}

int main()
{
	LL l,r;
	scanf("%lld%lld",&l,&r);
	printf("%lld\n",Solve(r)-Solve(l-1));
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/88311573