版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/88311573
题目
我琢磨着我怎么越来越会写标题了呢?
这个题很明显不是积性函数。
就像:51nod 1847 奇怪的数学题-对次小质因数下功夫。
而这个题是让我们求次大质因数。
考虑Min_25筛第二部分求答案的过程。
S(a,b)表示2~a中
的答案。
那么S(a,b)可以通过(套路)枚举质数和质数的次方,如果当前质数要当作次大质因数,
,如果不作,那就简单的
这个。。。由此我们推出结论,和所包含质数有关系的题,可以使用类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));
}