BZOJ3309 DZY Loves Math 【Mobius Inversion】

topic

For a positive integer n, define f(n) as the largest power exponent of the prime factors contained in n. For example f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0.
Given positive integers a, b, find sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b).

input format

The first line contains a number T, which represents the number of queries.
The next T lines, each with two numbers a, b, represent a query.

output format

For each query, output a line with a non-negative integer as the answer.

input sample

4

7558588 9653114

6514903 4451211

7425644 1189442

6335198 4957

Sample output

35793453939901

14225956593420

4332838845846

15400094813

hint

【Data scale】

T<=10000

1<=a,b<=10^7

answer

The previous derivation is very routine:
\[ans = \sum\limits_{i = 1}^{n} \sum\limits_{j = 1}^{m} f[gcd(i,j)]\]
\[= \sum\limits_{d = 1}^{n} f[d] * \sum\limits_{i = 1}^{\lfloor \frac{n}{d} \rfloor} \sum\limits_{j = 1 }^{\lfloor \frac{m}{d} \rfloor} [gcd(i,j) == 1]\]
\[=\sum\limits_{d = 1}^{n} f[d] * \sum\limits_{i = 1}^{\lfloor \frac{n}{d} \rfloor} \mu(i) * \lfloor \frac{n}{id} \rfloor\lfloor \frac{m}{ id} \rfloor\]
\[=\sum\limits_{T = 1}^{n} \lfloor \frac{n}{T} \rfloor\lfloor \frac{m}{T} \rfloor \sum\limits_ {d|T} f[d] * \mu(\frac{T}{d})\]
The thing behind \(g(T) = \sum\limits_{d|T} f[d] * \mu (\frac{T}{d})\) If it can be preprocessed, it can be \(O(T\sqrt{n})\) calculated
Then I will only \(O(nlogn)\) ,,, , the
film removal problem

To take advantage of the properties of \(\mu(i)\)
, obviously \(i\) does not have to consider the square term,
so \(T = \prod\limits_{i = 1}^{k} p_i^{a_i}\ ) in each \(a_i\) is removed at most \(1\)
set the maximum to \(r\)
so \(f(T) = r\) or \(r - 1\)
we have \( x\) such exponents are \(r\) , then the exponents of the remaining \(k - x\) prime factors can be chosen, and there is a \(2^{k - x}\) selection method
if \ (k \ne x\) , \(2^{k - x}\) is an even number, the positive and negative numbers corresponding to \(\mu\) are equal, and the final sum is \(0\)
so only \(k = x \) , \(g(T) \ne 0\)
otherwise we assume that all \(f(d)\) are equal to\(r\) , then the sum is still \(0\) , but in fact when the number of \(k\) is selected \(f(d) = r - 1\) , there is one more \(- 1\) , according to the parity, the contribution of \((-1)^{k + 1}\)
will finally be generated, so at this time \(g(T) = (-1)^{k + 1}\)

Specifically, you can filter out \(\mu(i)\) first , and then push out all \(f(i^x)\) from \(\mu(i) \ne 0\) \(i\ ) , so that Doing each number will only be pushed once, so it is \(O(n)\ )

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 10000005,maxm = 100005,N = 1e7,INF = 1000000000;
inline int read(){
    int out = 0,flag = 1; char c = getchar();
    while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    return out * flag;
}
int p[maxn],pi,isn[maxn],mu[maxn];
LL g[maxn];
void init(){
    mu[1] = 1;
    for (int i = 2; i <= N; i++){
        if (!isn[i]) p[++pi] = i,mu[i] = -1;
        for (int j = 1; j <= pi && i * p[j] <= N; j++){
            isn[i * p[j]] = true;
            if (i % p[j] == 0){
                mu[i * p[j]] = 0;
                break;
            }
            mu[i * p[j]] = -mu[i];
        }
    }
    for (LL i = 2; i <= N; i++)
        if (mu[i] != 0){
            for (LL j = i,t = -mu[i]; j <= N; j *= i)
                g[j] = t;
        }
    for (int i = 1; i <= N; i++) g[i] += g[i - 1];
}
int main(){
    init();
    int T = read(),n,m;
    LL ans;
    while (T--){
        n = read(); m = read(); ans = 0;
        if (n > m) swap(n,m);
        for (int i = 1,nxt; i <= n; i = nxt + 1){
            nxt = min(n / (n / i),m / (m / i));
            ans += 1ll * (n / i) * (m / i) * (g[nxt] - g[i - 1]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325068125&siteId=291194637