P4213 【模板】杜教筛(Sum) min_25筛

\(\color{#0066ff}{ 题目描述 }\)

给定一个正整数\(N(N\le2^{31}-1)\)

\(ans_1=\sum_{i=1}^n\varphi(i)\)

\(ans_2=\sum_{i=1}^n \mu(i)\)

\(\color{#0066ff}{输入格式}\)

一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N,代表一组询问

\(\color{#0066ff}{输出格式}\)

一共T行,每行两个用空格分隔的数ans1,ans2

\(\color{#0066ff}{输入样例}\)

6
1
2
8
13
30
2333

\(\color{#0066ff}{输出样例}\)

1 1
2 0
22 -2
58 -3
278 -3
1655470 2

\(\color{#0066ff}{数据范围与提示}\)

none

\(\color{#0066ff}{ 题解 }\)

可以用min_25筛写

对于\(\varphi\)

要拆成两个,一个0次项,一个1次项

在收集答案的时候直接加它们两个的差即可

对于\(\mu\)

因为只要指数超过1,就是0了,没用的,不同统计,直接统计1次的就行

#include<bits/stdc++.h>
#define LL long long
LL in() {
    char ch; LL x = 0, f = 1;
    while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    return x * f;
}
const int maxn = 2e6 + 10;
LL g0[maxn], g1[maxn], a[maxn];
int pri[maxn];
int m, sqt, n, tot;
int getid(LL x) { return x <= sqt? x : m - n / x + 1; }
LL getphi(LL a, int b) {
    if(a < pri[b]) return 0;
    LL ans = (g1[getid(a)] - g1[getid(pri[b - 1])]) - (g0[getid(a)] - g0[getid(pri[b - 1])]);
    for(int i = b; i <= tot && (LL)pri[i] * pri[i] <= a; i++)
        for(LL x = pri[i], f = pri[i] - 1; x * pri[i] <= a; x *= pri[i], f *= pri[i])
             //phi[p^2]的贡献是p*(p-1)
            ans += (getphi(a / x, i + 1) * f + f * pri[i]);
    return ans;
}
LL getmu(LL a, int b) {
    if(a < pri[b]) return 0;
    LL ans = -g0[getid(a)] + g0[getid(pri[b - 1])];
    //只需枚举质数,次数就是1即可
    for(int i = b; i <= tot && (LL)pri[i] * pri[i] <= a; i++)
        //乘的那个f是-1,所以直接减,加的那个f是平方项=0, 不用管
        ans -= getmu(a / pri[i], i + 1);
    return ans;
}
int main() {
    for(int T = in(); T --> 0;) {
        n = in();
        sqt = sqrt(n);
        m = tot = 0;
        for(int i = 1; i <= n; i = a[m] + 1)
            a[++m] = n / (n / i), g0[m] = a[m] - 1, g1[m] = a[m] * (a[m] + 1) / 2 - 1;
        for(int i = 2; i <= sqt; i++) {
            if(g0[i] != g0[i - 1]) {
                LL sqr = i * i;
                pri[++tot] = i;
                for(int j = m; a[j] >= sqr; j--) {
                    int id = getid(a[j] / i);
                    g0[j] -= g0[id] - g0[i - 1];
                    g1[j] -= i * (g1[id] - g1[i - 1]);
                }
            }
        }
        printf("%lld %lld\n", getphi(n, 1) + 1, getmu(n, 1) + 1);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/olinr/p/10284336.html

时间: 2024-10-09 07:20:27

P4213 【模板】杜教筛(Sum) min_25筛的相关文章

luoguP4213 [模板]杜教筛

https://www.luogu.org/problemnew/show/P4213 同 bzoj3944 考虑用杜教筛求出莫比乌斯函数前缀和,第二问随便过,第一问用莫比乌斯反演来做,中间的整除分块里的莫比乌斯前缀和刚好用第二问来做 杜教筛的时候先线性筛出前 N 个数的莫比乌斯函数前缀和,其余的用 map 记忆化搜索,实测 N 取 3670000 最佳(其实我只测了3次) #include <bits/stdc++.h> using namespace std; typedef unsign

[模板]杜教筛

用途 比线性更快($O(n^{\frac{2}{3}})$)地求积性函数的前缀和 前置知识:狄利克雷卷积 形如$h(n)=\sum\limits_{d|n}f(d)g(\frac{n}{d})$,则称$h(n)=f(x)*g(x)$ 如果f和g都是积性函数,则卷出的h也是积性函数 可以证明,狄利克雷卷积满足交换律.结合律.分配律 比较重要的卷积式子(抄的..): $$\mu*1=\varepsilon , \varepsilon(n)=[n=1]$$ $$\varphi*1=id , id(n)

P4213 【模板】杜教筛(Sum)

\(\color{#0066ff}{题 目 描 述}\) 给定一个正整数\(N(N\le2^{31}-1)\) 求 \(\begin{aligned} ans_1=\sum_{i=1}^n\varphi(i) \end{aligned}\) \(\begin{aligned} ans_2=\sum_{i=1}^n \mu(i) \end{aligned}\) \(\color{#0066ff}{输 入 格 式}\) 一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N

P4213【模板】杜教筛(Sum)

思路:杜教筛 提交:\(2\)次 错因:\(\varphi(i)\)的前缀和用\(int\)存的 题解: 对于一类筛积性函数前缀和的问题,杜教筛可以以低于线性的时间复杂度来解决问题. 先要构造\(h=f*g\),并且\(h\)的前缀和易求,\(g\)的区间和易求. 具体地: \[\sum_{i=1}^{n}h(i)=\sum_{i=1}^{n}\sum_{d|i}g(d)\cdot f(\frac{i}{d})\] \[\sum_{i=1}^{n}h(i)=\sum_{d=1}^{n}g(d)\

洛谷P4213 Sum(杜教筛)

题目描述 给定一个正整数N(N\le2^{31}-1)N(N≤231−1) 求ans_1=\sum_{i=1}^n\phi(i),ans_2=\sum_{i=1}^n \mu(i)ans1?=∑i=1n??(i),ans2?=∑i=1n?μ(i) 输入输出格式 输入格式: 一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N,代表一组询问 输出格式: 一共T行,每行两个用空格分隔的数ans1,ans2 输入输出样例 输入样例#1: 复制 6 1 2 8 13 30 2

【模板】杜教筛(Sum)

传送门 Description 给定一个正整数\(N(N\le2^{31}-1)\) 求 \[ans1=\sum_{i=1}^n \varphi(i)\] \[ans_2=\sum_{i=1}^n \mu(i)\] Solution 总算是写了一个不会\(TLE\)的杜教筛,不想用\(map\),因此上了一个很丑的\(Hash\)-- Code #include<bits/stdc++.h> #define ll long long #define max(a,b) ((a)>(b)?(

3944: Sum(杜教筛)

3944: Sum Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 4930  Solved: 1313[Submit][Status][Discuss] Description Input 一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N,代表一组询问 Output 一共T行,每行两个用空格分隔的数ans1,ans2 Sample Input 6 1 2 8 13 30 2333 Sample Output 1 1

●杜教筛入门(BZOJ 3944 Sum)

入门杜教筛啦. http://blog.csdn.net/skywalkert/article/details/50500009(好文!) 可以在$O(N^{\frac{2}{3}})或O(N^{\frac{3}{4}})$的复杂度内解决求某些数论函数f(n)(或f的前缀和S(n)$)的值. 先来看看原理是什么.(接下来推导如何求数论函数f(n)的前缀和S(n)) 现在有两个数论函数$f( )和g( )$ (同时定义f的前缀和函数$S(n)=\sum_{i=1}^{n}f(i)$) 有狄利克雷乘

[模板][P3377]杜教筛

Description: 求 $ \sum_{i=1}^n \phi(i) ,\sum_{i=1}^n \mu(i)$ Hint: \(n<=10^{10}?\) Solution: 考虑积性函数 \(f,g,h?\) 及其前缀和 \(F,G,H?\) 其中 \(h=f*g?\) 首先 \(H(x)=\sum_{n=1}^xh(n)\) \(=\sum_{n=1}^x \sum_{d|n} f(d) g(\frac{n}{d})\) 枚举倍数转枚举因数 \(=\sum_{k=1}^x \sum_