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;
}