首页 > 其他分享 >Min25筛

Min25筛

时间:2023-01-16 22:55:41浏览次数:43  
标签:lfloor frac int Min25 sqrt sum 质数

博客两年没更了,其实博主有在打 ACM,但是因为平时用 Latex 而不是 Markdown 所以就算写了点东西也懒得搬,最近准备搬点知识点总结过来

用途

求积性函数 \(f\) 的前缀和 \(F(n)=\sum_n^{i=1} f(i)\).

复杂度 \(O(\frac{n^{\frac{3}{4}}}{\log{n}})\) (或者 \(O(n^{1-\epsilon})\), 存在 \(O(n^{\frac{2}{3}})\) 的树状数组优化版本, 但常数巨大)

使用条件

  • \(f(p)\) 是低次多项式(感觉是完全积性函数的线性组合就行?)
  • \(f(p^e)\) 可以快速求出

原理

Part 1

对于完全积性函数 \(f_k(i)=i^k\), 求解 \(\sum_{p_i \le n} f_k(p_i)\), 其中 \(p_i\) 是第 \(i\) 小的质数.

通过埃氏筛的方式只留下合法位置, 这样质数只需要筛到 \(\sqrt{n}\) 就可以把合数位置全部去除.

设 \(g_k(n,i)\) 为用前 \(i\) 个质数做埃氏筛, 前 \(n\) 个数剩余合法位置的 \(f_k\) 的和, 即

\[ g_k(n,i)=\sum_{j=2}^{n}{[MinP(j) > p_i \lor j \in P] \cdot f_k(j)} \]

其中, \(MinP(j)\) 为 \(j\) 的最小质因数.

考虑埃氏筛的过程:

首先, \(1\) 从一开始就被筛去, 因此 \(g_k(n,0) = \sum_{i=2}^{n} f_k(p_i)\), 即自然数幂和减 \(1\).

接下来每个数被其最小质因数筛去.

\[ g_k(n,i)=g_k(n,i-1)-\sum_{j=p_i+1}^{n}{[MinP(j)=P]\cdot f_k(j)}\\ =g_k(n,i-1)-f_k(p_i)\cdot\sum_{j=p_i+1}^{n}{[MinP(j)=P]\cdot f_k(\frac{j}{p_i})}\\ =g_k(n,i-1)-f_k(p_i)\cdot\sum_{j=p_i}^{\lfloor \frac{n}{p_i} \rfloor}{[MinP(j)\ge P]\cdot f_k(j)}\\ g_k(n,i-1)-f_k(p_i)\cdot(g_k(\lfloor \frac{n}{p_i} \rfloor,i-1)-\sum_{j=1}^{i-1}f_k(p_i)) \]

记 \(\sum_{j=1}^{i-1}f_k(p_i)\) 为 \(sp_k(i-1)\), 可以线性筛预处理.

根据这个式子可以dp, 但时间和空间复杂度都不能接受.

可以注意到,第 \(i\) 次筛后的 \(g\) 数组是由第 \(i-1\) 次筛后的 \(g\) 数组转移而来, 且转移点 \(\lfloor \frac{n}{p_i} \rfloor < n\), 所以可以直接省掉一维.

注意到每次转移点都是 \(\lfloor \frac{n}{x} \rfloor\) 的形式,
由于 \(\lfloor \frac{\lfloor \frac{n}{a} \rfloor}{b} \rfloor = \lfloor \frac{n}{ab} \rfloor\),
所以为了求 \(g_k(n,i)\) 实际需要用到的位置不超过 \(2\sqrt{n}\) 个.

将这 \(2\sqrt{n}\) 个位置拼成一个数组, 只计算这些位置的值, 看起来就非常优秀了.

由于对于 \(g_k(n,\infty)\), 只需要枚举不超过 \(\sqrt{n}\) 的质数, 总复杂度为:

\[ T(n)=\sum_{i=1}^{\sqrt{n}}O(\pi(\sqrt{i}))+\sum_{i=1}^{\sqrt{n}}O(\pi(\sqrt{\lfloor \frac{n}{i} \rfloor}))\\ =\sum_{i=1}^{\sqrt{n}}O(\pi(\sqrt{\frac{n}{i}}))\\ =\sum_{i=1}^{\sqrt{n}}O(\frac{\sqrt{\frac{n}{i}}}{\log(\frac{n}{i})})\\ =O(\int_{1}^{\sqrt{n}}\frac{\sqrt{\frac{n}{x}}}{\log(\sqrt{\frac{n}{x}})} \mathrm{d}x)\\ =O(\frac{\sqrt{n}}{\log n}\int_{1}^{\sqrt{n}}x^{-\frac{1}{2}} \mathrm{d}x)\\ =O(\frac{n^{\frac{3}{4}}}{\log n}) \]

这样,就对所有 \(m = \lfloor \frac{n}{x} \rfloor\) 的位置都求出了\(\sum_{p_i \le m} f_k(p_i)\), 如果\(f(i)\)只在质数位置不为\(0\)(如求质数个数等, 就已经做完了).

Part 2

接下来求解 \(\sum_{i=1}^{n}f(i)\), 设:

\[S(n,i)=\sum_{j=2}^{n}{[MinP(j)>p_i] \cdot f(j)} \]

所求即为 \(S(n,0)+1\).

分别考虑质数和合数位置对 \(S(n,i)\) 的贡献:

  • 对质数位置, \(f(i)\) 是低次多项式, \(i^k\)的贡献为 \(g_k(n,\infty)-sp_k(i)\), 容易算出总贡献.

  • 对合数位置, 需要枚举其最小质因子及其次数, 根据积性函数的性质知道,贡献为:

\[\sum_{j>i}\sum_{p_j^e\le n}f(p_j^e)(S(\lfloor \frac{n}{p_j^e} \rfloor,j)+[e\neq 1]) \]

似乎因为某些深刻的原因(好像是只会每个位置访问一次)直接递归计算就行, 复杂度是 \(O(n^{1-\epsilon})\) 的, 但常数巨小, 在\(n \le 10^{13}\)时和\(O(\frac{n^{\frac{3}{4}}}{\log{n}})\)等数量级.
如果也写成dp递推就同样是 \(O(\frac{n^{\frac{3}{4}}}{\log{n}})\) 的.

例题

\(f(p^k)=p^k(p^k-1)\), 求 \(\sum_{i=1}^{n} f(i)\)

ll n;
int sq,m;

int tot;
int prime[N];
bool mark[N];

int sp1[N]; // f1 在前 n 个质数位置的前缀和
int sp2[N]; // f2 在前 n 个质数位置的前缀和

int g1[N*2]; // f1 在不超过 m = n/x 的质数位置的前缀和
int g2[N*2]; // f2 在不超过 m = n/x 的质数位置的前缀和

ll w[N*2];
int Ind1[N];
int Ind2[N];

// 注意 n 是全局变量
inline int& index(const ll &x){
    return x<=sq?Ind1[x]:Ind2[n/x];
}

// f'(x) 与 积性函数 f(x) 在质数位置相等 
// 且 f'(x) 为 f2(x) 与 f1(x) 的差
// f'(x) = x * (x - 1) = x^2 - x
inline ll f(ll x){
    x%=p;
    return x*(x-1)%p;
}

// f1(x) = x
inline ll f1(ll x){
    return x;
}

// f2(x) = x^2
inline ll f2(ll x){
    return x*x%p;
}

// f1 的前缀和
inline ll s1(ll x){
    x%=p;
    return x*(x+1)/2%p;
}

// f2 的前缀和
inline ll s2(ll x){
    x%=p;
    return x*(x+1)%p*(2*x+1)%p*inv6%p;
}

inline ll S(ll x,int j){
    if(prime[j]>x)return 0;
    // 质数位置的贡献
    int ans=sub(sub(g2[index(x)],g1[index(x)]),sub(sp2[j],sp1[j]));
    for(int i=j+1;i<=tot&&(ll)prime[i]*prime[i]<=x;++i){
        for(ll e=1,pk=prime[i];pk<=x;++e,pk*=prime[i]){
            // 合数位置的贡献(枚举最小质因子及其次幂)
            ans=add(ans,mul(f(pk),add(S(x/pk,i),(e>1))));
        }
    }
    return ans;
}

int main(){
    r(n);
    sq=sqrt(n);
    for(int i=2;i<=sq;++i){
        if(!mark[i]){
            prime[++tot]=i;
            sp1[tot]=add(sp1[tot-1],f1(i));
            sp2[tot]=add(sp2[tot-1],f2(i));
        }
        for(int j=1,tmp;j<=tot&&(tmp=i*prime[j])<=sq;++j){
            mark[tmp]=1;
            if(i%prime[j]==0)break;
        }
    }
    for(ll i=1,j;i<=n;i=j+1){
        w[++m]=n/i;
        j=n/w[m];
        index(w[m])=m;
        g1[m]=sub(s1(w[m]),1); // 先筛掉 1, f1(1)=1
        g2[m]=sub(s2(w[m]),1); // 先筛掉 1, f2(1)=1
    }
    for(int i=1;i<=tot;++i){
        for(int j=1;j<=m&&(ll)prime[i]*prime[i]<=w[j];++j){
            g1[j]=sub(g1[j],mul(f1(prime[i]),sub(g1[index(w[j]/prime[i])],sp1[i-1])));
            g2[j]=sub(g2[j],mul(f2(prime[i]),sub(g2[index(w[j]/prime[i])],sp2[i-1])));
        }
    }
    printf("%d\n",add(S(n,0),1)); // 还原 f(1) 的贡献(因为是积性函数所以一定是 1 )
    return 0;
}

标签:lfloor,frac,int,Min25,sqrt,sum,质数
From: https://www.cnblogs.com/yicongli/p/17056507.html

相关文章

  • Loj 6053 简单的函数 min25筛
    #6053.简单的函数先求g(n,j)目的是为了在求S(n,j)的时候可以快速获取一些质数上的点的值。所以我们只要求g(n,j)的质数处的值正确即可其他值则不需要所以我们可以让g......
  • 【XSY3473】Frog(min25筛)
    一些记号:记\(\mathbb{P}\)为质数集,\(p_i\)表示第\(i\)个质数。记\(\operatorname{lpf}(x)\)表示\(x\)的最小质因数为第几个质数。特别地,令\(\operatorname{l......