[BZOJ3944]Sum

Posted xjr_01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ3944]Sum相关的知识,希望对你有一定的参考价值。

[BZOJ3944]Sum

试题描述

技术分享图片

输入

一共 \(T+1\)

\(1\) 行为数据组数 \(T(T \le 10)\)

\(2\) ~ \(T+1\) 行每行一个非负整数 \(N\),代表一组询问

输出

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

输入示例

6
1
2
8
13
30
2333

输出示例

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

数据规模及约定

见“试题描述”和“输入

题解

杜教筛模板(这个居然也有模板。。。)

既然用了 markdown 就再把核心公式打一遍吧。

\(F(n) = \sum_{i=1}^n {\mu (i)}\)\(G(n) = \sum_{i=1}^n {\varphi(i)}\)

\(\sum_{i=1}^n {F(\lfloor \frac{n}{i} \rfloor)} = \sum_{i=1}^n {\sum_{d|i}} {\mu (d)} = 1 \Rightarrow F(n) = 1 - \sum_{i=2}^n {F(\lfloor \frac{n}{i} \rfloor)}\)

\(\sum_{i=1}^n {G(\lfloor \frac{n}{i} \rfloor)} = \sum_{i=1}^n {\sum_{d|i}} {\varphi (d)} = \frac{n(n+1)}{2} \Rightarrow G(n) = \frac{n(n+1)}{2} - \sum_{i=2}^n {G(\lfloor \frac{n}{i} \rfloor)}\)

注意这题的数据范围,\(n\) 加个 \(1\) 就爆 int 了!!!建议把所有加好搜索一下然后依次开 long long。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <map>
using namespace std;
#define rep(i, s, t) for(int i = (s); i <= (t); i++)
#define dwn(i, s, t) for(int i = (s); i >= (t); i--)

int read() {
    int x = 0, f = 1; char c = getchar();
    while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); }
    while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); }
    return x * f;
}

#define LL long long
#define maxn 2500010
int prime[maxn], cp, _phi[maxn], mu[maxn], su[maxn];
LL sp[maxn];
bool vis[maxn];
map <int, LL> phi;
map <int, int> u;

void init() {
    sp[1] = su[1] = 1;
    rep(i, 2, maxn - 1) {
        if(!vis[i]) prime[++cp] = i, mu[i] = -1, _phi[i] = i - 1;
        for(int j = 1; j <= cp && i * prime[j] < maxn; j++) {
            vis[i*prime[j]] = 1;
            if(i % prime[j] == 0) {
                mu[i*prime[j]] = 0;
                _phi[i*prime[j]] = _phi[i] * prime[j];
                break;
            }
            mu[i*prime[j]] = -mu[i];
            _phi[i*prime[j]] = _phi[i] * (prime[j] - 1);
        }
        su[i] = su[i-1] + mu[i];
        sp[i] = sp[i-1] + _phi[i];
    }
    return ;
}

LL calcphi(int n) {
    if(n < maxn) return sp[n];
    if(phi.count(n)) return phi[n];
    LL ans = ((LL)n + 1) * n >> 1;
    for(int i = 2; i <= n;) {
        int j = min(n / (n / i), n);
        ans -= calcphi(n / i) * (j - i + 1);
        if(j >= n) break;
        i = j + 1;
    }
    return phi[n] = ans;
}
int calcu(int n) {
    if(n < maxn) return su[n];
    if(u.count(n)) return u[n];
    int ans = 1;
    for(int i = 2; i <= n;) {
        int j = min(n / (n / i), n);
        ans -= calcu(n / i) * (j - i + 1);
        if(j >= n) break;
        i = j + 1;
    }
    return u[n] = ans;
}

int main() {
    init();
    
    int T = read();
    while(T--) {
        int n = read();
        printf("%lld %d\n", calcphi(n), calcu(n));
    }
    
    return 0;
}

以上是关于[BZOJ3944]Sum的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ3944]Sum

bzoj3944Sum

BZOJ_3944_Sum_杜教筛

Bzoj3944 Sum

Sum BZOJ 3944

bzoj3944 Sum