BZOJ 4659: Lcm
\[题意:求\sum_{i = 1} ^ A \sum_{j = 1} ^ B lcm(i, j) \cdot \mu ^ 2(gcd(i, j))
\]
\[\begin{eqnarray*}
题目所求的是\sum_{i = 1} ^ A \sum_{j = 1} ^ B lcm(i, j) \cdot \mu ^ 2(gcd(i, j)) \nonumber \\
我们发现\\
Ans & = & \sum_{i = 1} ^ A \sum_{j = 1} ^ B lcm(i, j) \cdot \mu ^ 2(gcd(i, j)) \nonumber \\
& = & \sum_{i = 1} ^ A \sum_{j = 1} ^ B \sum_{d \mid i, d \mid j} [gcd(i, j) == d] \frac{i \cdot j}{d} \cdot \mu ^ 2(d) \nonumber \\
& =& \sum_{d = 1} ^ A \sum_{i = 1} ^ {\lfloor \frac{A}{i} \rfloor} \sum_{j = 1} ^ {\lfloor \frac{B}{j} \rfloor} [gcd(i, j) == 1] \cdot d \cdot i \cdot j \cdot \mu ^ 2(d) \nonumber \\
& = &\sum_{d=1} ^ A \mu ^ 2(d) \cdot d \sum_{i = 1} ^ {\lfloor \frac{A}{d} \rfloor} i \sum_{ j = 1} ^ {\lfloor \frac{B}{d} \rfloor} j \sum_{e \mid i, e \mid j} \mu(e) \nonumber \\
& = &\sum_{d=1} ^ A \mu ^ 2(d) \cdot d \sum_{e = 1} ^ {\lfloor \frac{A}{d} \rfloor} \mu(e) \cdot e ^ 2 \sum_{i = 1} ^ {\lfloor \frac{A}{d \cdot e} \rfloor} i \sum_{j = 1}^{\lfloor \frac{B}{d \cdot e} \rfloor} j \nonumber \\
& = &\sum_{D=1}^AD\sum_{d \mid D}\mu ^2 (d)\cdot \mu(\frac{D}{d})\cdot \frac{D}{d}\cdot sum(\lfloor \frac{A}{D} \rfloor) \cdot sum(\lfloor \frac{B}{D} \rfloor) \\
发现f(x)=\sum_{d \mid x} g(x) \cdot h(\frac{x}{d})\\
g(x)为极性函数\\
h(x)为极性函数\\
所以f(x)为积性函数
\end{eqnarray*}
\]
\[O(n\cdot log_n)解法
\]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps = 1e-8;
const int MOD = 1 << 30;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
const int maxn = 4e6 + 10;
bool check[maxn];
int prime[maxn];
int mu[maxn];
int f[maxn];
void Moblus()
{
mu[1] = 1;
int tot = 0;
for (int i = 2; i < maxn; ++i)
{
if (!check[i])
{
prime[tot++] = i;
mu[i] = -1;
}
for (int j = 0; j < tot; ++j)
{
if (i * prime[j] >= maxn) break;
check[i * prime[j]] = true;
if (i % prime[j] == 0)
{
mu[i * prime[j]] = 0;
break;
}
else
{
mu[i * prime[j]] = -mu[i];
}
}
}
for (int i = 1; i < maxn; i++) if (mu[i] != 0)
{
for (int j = 1; j * i < maxn; j++)
{
int t = j * i;
f[t] += i * j * j * mu[j];
}
}
for (int i = 2; i < maxn; i++) f[i] += f[i - 1];
}
int n, m;
int SUM(int x)
{
return x * (x + 1) / 2;
}
void RUN()
{
Moblus();
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d %d", &n, &m);
int ans = 0;
for (int i = 1, la = 0; i <= min(n, m); i = la + 1)
{
la = min(n / (n / i), m / (m / i));
ans += SUM(n / i)*SUM(m / i)*(f[la] - f[i - 1]);
}
printf("%d\n", (ans % MOD + MOD) % MOD);
}
}
int main()
{
#ifdef LOCAL_JUDGE
freopen("Text.txt", "r", stdin);
#endif // LOCAL_JUDGE
RUN();
return 0;
}
\[O(n)解法
\]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps = 1e-8;
const ll MOD = 1073741824;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
const int maxn = 4e6 + 10;
bool check[maxn];
int prime[maxn];
unsigned int f[maxn];
void Moblus()
{
f[1] = 1;
int tot = 0;
for (int i = 2; i < maxn; ++i)
{
if (!check[i])
{
prime[tot++] = i;
f[i] = 1 - i;
}
for (int j = 0; j < tot; ++j)
{
if (i * prime[j] > maxn) break;
check[i * prime[j]] = true;
if (i % prime[j] == 0)
{
if (i % (prime[j] * prime[j]) == 0)
{
f[i * prime[j]] = 0;
}
else
{
f[i * prime[j]] = -f[i / prime[j]] * prime[j];
}
break;
}
f[i * prime[j]] = f[i] * (1 - prime[j]);
}
}
for (int i = 2; i < maxn; ++i) f[i] = f[i] * i + f[i - 1];
}
ll n, m;
unsigned int SUM(int x)
{
return (unsigned int)x * (x + 1) / 2;
}
void RUN()
{
Moblus();
int t;
scanf("%d", &t);
while (t--)
{
scanf("%lld %lld", &n, &m);
if (n > m) swap(n, m);
unsigned int ans = 0;
for (int i = 1, la = 0; i <= n; i = la + 1)
{
la = min(n / (n / i), m / (m / i));
ans += (f[la] - f[i - 1]) * SUM(n / i) * SUM(m / i);
}
printf("%u\n", ans % MOD);
}
}
int main()
{
#ifdef LOCAL_JUDGE
freopen("Text.txt", "r", stdin);
#endif // LOCAL_JUDGE
RUN();
return 0;
}