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;
}
posted @ 2019-04-13 10:23  薛37  阅读(101)  评论(0编辑  收藏  举报