Luo Gu P4213 [template] Du teach sieve (Sum) Du teach sieve

P4213 [template] Du teach sieve (Sum)

label

  • Du teach sieve

Foreword

  • Du teach screen template ~
  • Pre-knowledge is a linear screen, Mobius inversion, Dirichlet convolution - if not, you need to learn a little bit again learn to teach Du screen ~

Concise meaning of the questions

  • Request \ (\ MU \) and \ (\ Phi \) prefix and, in the range of \ (2 ^ {31} -1 \) , multiple inquiry.

Thinking

  • Du teach template screen. First, the core Du sieve is taught the following equation:
    \ [G (. 1) * S (n-) = \ sum_. 1} ^ {n-I = (F * G) (I) - \ sum_ I = {2} ^ ng (i) S [\ frac ni] \]
  • As long as the determined observation \ (G \) formula prefix and rearmost on the block. So for a multiplicative function, as long as we find a
  1. Prefix and easy to find
  2. Easy summation of the original function of the Dirichlet convolution function

Function g, it can be done.

  • Look at \ (\ mu \) function. Easy to know \ (\ * MU the I = \ Epsilon \) , then make \ (G = the I \) , then the first \ (g \) with \ (I \) substitution, then we ask for \ (\ MU \) substituting replace \ (F \) : \
    [\ SUM \ limits_. 1} ^ {n-I = (\ G * MU) (I) = \ SUM \ limits_. 1} ^ {n-I = (\ MU * I) (i) \]

    \ (\ mu * I = \ epsilon \) is a commonly used formula. prove:
    • Dirichlet convolution by the \ (\ mu * I = \ sum \ limits_ {d | n} \ mu (d) * I ([\ frac nd]) \)
    • And \ (the I (X) =. 1 \) , into the above equation, can know \ (\ mu * I = \ sum \ limits_ {d | n} \ mu (d) \)
    • And a Mobius inversion (may also be called Möbius function properties) can know \ (\ sum \ limits_ {d | n} \ mu (d) = [n == 1] = \ epsilon \) , there is substituted into the original formula:
      \ [\ * the I MU = \ Epsilon \]
  • Then it is easy to know \ (\ * the I MU = \ Epsilon \) , so it would be the original formula:
    \ [\ SUM \ limits_. 1} ^ {n-I = \ Epsilon (I) = [n-> =. 1] \]
  • Simply great prayed. Original into this formula it would be:
    \ [S (n-) = [n-> =. 1] - \ sum_ {2} = I ^ nS [\ FRAC Ni] \]
  • The second problem is now to find the formula \ (\ SUM \ limits_ I = {2} ^ ng (I) S [\ FRAC Ni] \) , block it, just simple.

---------------------------------------------- division line pigeon - ---------------------------------------------

  • Now seeking \ (\ phi \) prefix and. Almost very simple with the front duck. Self deriving it ~
    ---------------------------------------------- sub-pigeon line ----------------------------------------------
  • First of all this is the memory of the search, but will badly QAQ T
  • optimization. Although Du teach sieve is lower than the linear complexity, but group asked how the duck! When multiple sets of inquiry, the complexity of the linear screen but better than Du teach sieve (linear sieve \ (O (the n-\) ) pretreatment, then \ (O (1) \) query, but Du teaching screen ...) so we can look ahead linear sieve, sieve out the pretreatment can out of \ (\ mu and \ phi \) prefix and then Du screen can teach much faster! ! !

Precautions

  • 5e6 linear advance sieve sieve probably more appropriate ~

to sum up

  • This was memorizing common Dirichlet convolution, and then find the time function g will soon! Here we summarize common Dirichlet convolution:
  • \ (\ Mu * I = \ epsilon \)
  • \(\phi*I=id\)

AC Code

#include<cstdio>
#include<unordered_map>
using namespace std;

const int maxn = 5e6 + 10;

bool no_prime[maxn];
int prime[maxn], mu[maxn], phi[maxn], p_mu[maxn];
long long p_phi[maxn];
int shai(int n)
{
    int cnt = 0;
    mu[1] = phi[1] = 1;

    for (int i = 2; i <= n; i++)
    {
        if (!no_prime[i])
            prime[++cnt] = i, mu[i] = -1, phi[i] = i - 1;

        for (int j = 1; j <= cnt && prime[j] * i <= n; j++)
        {
            no_prime[i * prime[j]] = 1;
            mu[i * prime[j]] = i % prime[j] == 0 ? 0 : -mu[i];
            phi[i * prime[j]] = i % prime[j] == 0 ? phi[i] * prime[j] : phi[i] * (prime[j] - 1);
            if (i % prime[j] == 0) break;
        }
    }

    for (int i = 1; i <= n; i++)
        p_mu[i] = p_mu[i - 1] + mu[i], p_phi[i] = p_phi[i - 1] + phi[i];

    return cnt;
}

unordered_map<int, int> rec_mu;
unordered_map<int, long long> rec_phi;

int pre_mu(int n)
{
    if (n <= maxn - 10) return p_mu[n];
    if (rec_mu[n]) return rec_mu[n];

    int l = 2, r, ans = (n >= 1);
    while (l <= n)
    {
        r = n / (n / l);
        ans -= (r - l + 1) * pre_mu(n / l);
        l = r + 1;
    }
    return rec_mu[n] = ans;
}

long long pre_phi(int n)
{
    if (n <= maxn - 10) return p_phi[n];
    if (rec_phi[n]) return rec_phi[n];

    int l = 2, r;

    long long ans = n % 2 == 0 ? 1ll*n / 2ll * (n + 1) : (n + 1ll) / 2ll * n;
    while (l <= n)
    {
        r = n / (n / l);
        ans -= (r - l + 1) * pre_phi(n / l);
        if (l == 2147483647) break;
        l = r + 1;
    }
    return rec_phi[n] = ans;
}

void solve()
{
    shai(maxn - 10);

    int t;
    scanf("%d", &t);
    while (t--)
    {
        int n;
        scanf("%d", &n);

        printf("%lld %d\n", pre_phi(n), pre_mu(n));
    }
}

int main()
{
    solve();
    return 0;
}

Guess you like

Origin www.cnblogs.com/danzh/p/11302352.html