• [洛谷P4213]【模板】杜教筛(Sum)


    题目大意:给你$n$,求:
    $$
    sumlimits_{i=1}^nvarphi(i),sumlimits_{i=1}^nmu(i)
    $$
    最多$10$组数据,$nleqslant2^{31}-1$

    题解:杜教筛,用来求$sumlimits_{i=1}^nf(i)$的,其中$f$是某个特殊函数。

    若我们可以找到一个函数$g$,使得$g,f*g$两个函数的前缀和十分好算($g*f$表示$g$和$f$的狄利克雷卷积),就可在$O(n^{frac 23})$的复杂度内求出我们要的东西。令$S(n)=sumlimits_{i=1}^nf(i)$
    $$
    egin{align*}
    sumlimits_{i=1}^n(g*f)(i)&=sumlimits_{i=1}^nsumlimits_{d|i}g(d)fleft(dfrac id ight)\
    &=sumlimits_{d=1}^ng(d)sumlimits_{i=1,d|i}^nfleft(dfrac id ight)\
    &=sumlimits_{d=1}g(d)Sleft(leftlfloordfrac nd ight floor ight)
    end{align*}\
    g(1)S(n)=sumlimits_{i=1}^n(f*g)(i)-sumlimits_{i=2}^ng(i)Sleft(leftlfloordfrac ni ight floor ight)
    $$
    然后线性筛求出前$n^{frac23}$项,剩余的递归+整除分块计算,需要记忆化。

    $$
    sumlimits_{i=1}^nvarphi(i):\
    ecausevarphi*I=id\
    herefore S(n)=frac{n(n+1)}{2}-sum_{i=2}^nSleft(leftlfloordfrac n i ight floor ight)
    $$
    $$
    sumlimits_{i=1}^nmu(i):\
    ecausemu*I=1\
    herefore S(n)=1-sum_{i=2}^nSleft(leftlfloorfrac n i ight floor ight)
    $$

    注意这道题中$nleqslant2^{31}-1$,$+1$后会爆$int$,所以整除分块的时候要用$unsigned$

    卡点:

    C++ Code:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <unordered_map>
    const int R = 1 << 22 | 1;
    int plist[R >> 3], ptot;
    bool notp[R];
    long long phi[R], mu[R];
    void sieve() {
    	phi[1] = mu[1] = 1;
    	for (int i = 2; i < R; ++i){
    		if (!notp[i]) plist[ptot++]=i, phi[i] = i - 1, mu[i] = -1;
    		for(int j = 0, t; (t = i * plist[j]) < R; ++j){
    			notp[t] = true;
    			if(i % plist[j] == 0) {
    				phi[t] = phi[i] * plist[j];
    				mu[t] = 0;
    				break; }
    			phi[t] = phi[i] * phi[plist[j]];
    			mu[t] = -mu[i];
    		}
    	}
    	for (int i = 2; i < R; ++i) phi[i] += phi[i - 1], mu[i] += mu[i - 1];
    }
    std::unordered_map<unsigned, long long> Phi, Mu;
    long long sphi(unsigned n) {
    	if (n < R) return phi[n];
    	if (Phi.count(n)) return Phi[n];
    	long long &t = Phi[n];
    	for (unsigned l = 2, r; l <= n; l = r + 1) {
    		r = n / (n / l);
    		t += (r - l + 1) * sphi(n / l);
    	}
    	return t = static_cast<long long> (n + 1) * n / 2 - t;
    }
    long long smu(unsigned n) {
    	if (n < R) return mu[n];
    	if (Mu.count(n)) return Mu[n];
    	long long &t = Mu[n];
    	for (unsigned l = 2, r; l <= n; l = r + 1) {
    		r = n / (n / l);
    		t += (r - l + 1) * smu(n / l);
    	}
    	return t = 1 - t;
    }
    
    int T;
    int main() {
    	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cin.tie(0);
    	sieve();
    	std::cin >> T;
    	while (T --> 0) {
    		static unsigned n;
    		std::cin >> n;
    		std::cout << sphi(n) << ' ' << smu(n) << '
    ';
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    leetcode(85)最大矩形
    红黑树
    查询学生成绩表中大于60分的每一个成绩的人数
    聚合函数以及SQL中的一些小知识
    Oracle的JDBC
    StringBuffer的reverse方法
    查询时报第一页没有数据,第二页有数据的异常
    普通人如何从平庸到优秀,在到卓越
    HDMI、DVI、VGA等这些接口
    显卡上的VGA接口和高清接口有什么区别?
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/11326032.html
Copyright © 2020-2023  润新知