• LG P4213【模板】杜教筛(Sum)


    ( ext{Problem})

    [sum_{i=1}^n varphi(i) ]

    [sum_{i=1}^n mu(i) ]

    (1 le n < 2^{31})

    (Solution)

    终于开始学杜教筛了!!!
    求积性函数 (f) 的前缀和,杜教筛可以低于线性
    考虑卷积,构造积性函数 (h = f * g)
    然后套路地推出一个重要的结论

    [g(1)S(n)=sum_{i=1}^n(f*g)(i)-sum_{i=2}^n S(lfloor frac n i floor) ]

    这是一个递归式,快速计算这个式子
    要能快速 (h) 的前缀和,最后的式子整出分块
    提前筛出 (n^{frac 2 3}) 以内 (f) 的前缀和,算到直接使用
    ( ext{unordered_map}) 存下已经计算过的 (f) 的前缀和,进行记忆化

    然后对于本题就是利用

    [varphi * I = ID ]

    [mu * I = epsilon ]

    ( ext{Code})

    #include<cstdio>
    #include<tr1/unordered_map>
    #define LL long long
    using namespace std;
    
    tr1::unordered_map<int, LL> S_phi;
    tr1::unordered_map<int, int> S_mu;
    
    const int MAXN = 3e6;
    int vis[MAXN + 5], mu[MAXN + 5], prime[MAXN], totp;
    LL phi[MAXN + 5];
    inline void sieve()
    {
    	vis[1] = mu[1] = phi[1] = 1;
    	for(register int i = 2; i <= MAXN; i++)
    	{
    		if (!vis[i]) prime[++totp] = i, mu[i] = -1, phi[i] = i - 1;
    		for(register int j = 1; j <= totp && prime[j] * i <= MAXN; j++)
    		{
    			vis[i * prime[j]] = 1;
    			if (i % prime[j]) phi[i * prime[j]] = phi[i] * phi[prime[j]], mu[i * prime[j]] = -mu[i];
    			else{phi[i * prime[j]] = phi[i] * prime[j]; break;}
    		}
    	}
    	for(register int i = 1; i <= MAXN; i++) mu[i] += mu[i - 1], phi[i] += phi[i - 1];
    }
    
    LL Sum_phi(LL n)
    {
    	if (n <= MAXN) return phi[n];
    	if (S_phi[n]) return S_phi[n];
    	LL res = n * (n + 1) / 2, j;
    	for(register LL i = 2; i <= n; i = j + 1)
    	{
    		j = n / (n / i);
    		res -= (j - i + 1) * Sum_phi(n / i);
    	}
    	return S_phi[n] = res;
    }
    int Sum_mu(LL n)
    {
    	if (n <= MAXN) return mu[n];
    	if (S_mu[n]) return S_mu[n];
    	LL res = 1, j;
    	for(register LL i = 2; i <= n; i = j + 1)
    	{
    		j = n / (n / i);
    		res -= (j - i + 1) * Sum_mu(n / i);
    	}
    	return S_mu[n] = res;
    }
    
    int main()
    {
    	sieve();
    	int T; scanf("%d", &T);
    	for(; T; --T)
    	{
    		LL n; scanf("%lld", &n);
    		printf("%lld %d
    ", Sum_phi(n), Sum_mu(n));
    	}
    }
    
  • 相关阅读:
    说一说Java的Unsafe类
    阿里云CentOS下安装jdk
    LeetCode 5
    五种方法实现Java的Singleton单例模式
    聊聊Java的final关键字
    LeetCode 4
    Java9都快发布了,Java8的十大新特性你了解多少呢?
    【Spring】mvc:annotation-driven 使用
    【gradle】【maven】gradle 转 maven pom.xml
    [GIT]比较不同分支的差异
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/15017652.html
Copyright © 2020-2023  润新知