lahlahblog喵~

浅谈Min-25筛

lahlah·2022-01-14 22:16·56 次阅读

浅谈Min-25筛

U1S1这个东西真的nb

cz_xuyixuan【学习笔记】Min25筛

这个写得好!!!

我们通过一道题来入门

luogu P5325 【模板】Min_25筛

先考虑如何计算g(n,i)

我们把那个式子拆开,发现是f(p)=p2p

所以我们需要分别计算p2的和p

g(n,i)=j=1n[jP  or  Minj>p[i]]ik

其中的k对应为上面的1,2,Minj表示j的最小质因数

可以得到一个显然的转移
考虑把第i个质数p[i]的贡献挖掉
g(n,i)=g(n,i1)p[i]k(g(np[i]k,i1)sum[i1])
sum[i]表示前i个质数的贡献

这样我们就轻易得到了g(n,i)
显然|P|=in,通过这个可以在O(n34logn)的时间复杂度内计算出g(n,|P|)
所有质数对答案的贡献

我们再来

S(n,i)=j=1n[Minj>p[i]]f(j)

根据最终的定义,我们可以得到
i=1nf(i)=S(n,0)+f(1)

然后我们再来考虑如何求S(n,i)

因为f是积性函数,质数的部分我们上面已经求出来了,我们可以考虑枚举这个合数的最小值质因数和它的次数来转移

方程同样不难

S(n,i)=g(n,|P|)j=1i1f(p[j])+j>i&p[j]xn(f(p[j]x,j)+[x>1])

意思就是g(n,|P|)表示所有质数的贡献,因为Minj>p[i]所以还要把<p[i]的质数的贡献减掉

然后枚举合数的最小质因数p[j],以及次数x后面的[x>1]加上的是形容p?这样的数的贡献

这一部分计算的时间复杂度同样是O(n34logn)

然后就完事了,注意1要特殊处理

可以看代码理解

关于空间储存问题,我们发现n一定是Ni中的一个,所以可以提前处理出来
类似分块一样保存,就可以把空间压到O(n)

code:

Copy
#include<bits/stdc++.h> #define N 200050 #define mod 1000000007 #define ll long long using namespace std; int add(int x, int y) { x += y; if(x >= mod) x -= mod; return x; } int sub(int x, int y) { x -= y; if(x < 0) x += mod; return x; } int mul(int x, int y) { return 1ll * x * y % mod; } int qpow(int x, int y) { int ret = 1; for(; y; y >>= 1, x = mul(x, x)) if(y & 1) ret = mul(ret, x); return ret; } int p[N], sz, s[N][3], vis[N], blo; void get(int n) { for(int i = 2; i <= n; i ++) { if(!vis[i]) { p[++ sz] = i; s[sz][1] = add(s[sz - 1][1], i); s[sz][2] = add(s[sz - 1][2], mul(i, i));//预处理sum } for(int j = 1; j <= sz && p[j] * i <= n; j ++) { vis[p[j] * i] = 1; if(i % p[j] == 0) break; } } } ll n, w[N]; int id1[N], id2[N], gs, g[N][3]; int id(ll x) { if(x <= blo) return id1[x]; return id2[n / x]; } ll s1(ll x) { x %= mod; return 1ll * x * (x + 1) % mod * qpow(2, mod - 2) % mod; } ll s2(ll x) { x %= mod; return 1ll * x * (x + 1) % mod * (2 * x + 1) % mod * qpow(6, mod - 2) % mod; } ll f(ll x) { x %= mod; return mul(x, sub(x, 1)); } ll S(ll n, int m) { if(n <= p[m]) return 0; int ret = sub(sub(g[id(n)][2], s[m][2]), sub(g[id(n)][1], s[m][1]));//即p^2-p for(int j = m + 1; j <= sz && p[j] <= n / p[j]; j ++) { ll x = p[j]; for(int k = 1; x <= n; x = x * p[j], k ++) { ret = add(ret, mul(f(x), S(n / x, j) + (k > 1)));//把上面两个放在一起转移了,因为积性函数的和还是积性函数 } } return ret; } int main() { scanf("%lld", &n); get(blo = sqrt(n)); for(ll l = 1, r = 0; l <= n; l = r + 1) { r = n / (n / l); w[++ gs] = n / l; g[gs][1] = sub(s1(w[gs]), 1); g[gs][2] = sub(s2(w[gs]), 1);//维护k=1,2,这里的g是g(n,0) if(w[gs] <= blo) id1[w[gs]] = gs;//类似分块一样储存 else id2[n / w[gs]] = gs; } for(int i = 1; i <= sz; i ++) { for(int j = 1; j <= gs && p[i] <= w[j] / p[i]; j ++) {//g的转移,把第二维滚掉了 g[j][1] = sub(g[j][1], mul(p[i], sub(g[id(w[j] / p[i])][1], s[i - 1][1]))); g[j][2] = sub(g[j][2], mul(mul(p[i], p[i]), sub(g[id(w[j] / p[i])][2], s[i - 1][2]))); } } printf("%d", add(S(n, 0), 1)); return 0; }
posted @   lahlah  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示