【BZOJ】3309: DZY Loves Math

题意

\(T(T \le 10000)\)次询问,每次给出\(a, b(1 \le a, b \le 10^7)\),求

\[\sum_{i=1}^{a} \sum_{j=1}^{b} f((i, j)) \]

其中\(f(n)\)表示\(n\)所含质因子的最大幂指数。\(f(1)=0\)

分析

以下默认\(a \le b\)

$$ \begin{align} & \sum_{i=1}^{a} \sum_{j=1}^{b} f((i, j)) \\ = & \sum_{d=1}^{a} f(d) \sum_{i=1}^{a'} \sum_{j=1}^{b'} [(i, j)=1] & \left( a' = \left \lfloor \frac{a}{d} \right \rfloor, b' = \left \lfloor \frac{b}{d} \right \rfloor \right) \\ = & \sum_{d=1}^{a} f(d) \sum_{i=1}^{a'} \sum_{j=1}^{b'} \sum_{k|(i, j)} \mu(k) \\ = & \sum_{d=1}^{a} f(d) \sum_{k=1}^{\left \lfloor \frac{a}{d} \right \rfloor} \mu(k) \left \lfloor \frac{a}{kd} \right \rfloor \left \lfloor \frac{b}{kd} \right \rfloor \\ = & \sum_{T=1}^{a} \left \lfloor \frac{a}{T} \right \rfloor \left \lfloor \frac{b}{T} \right \rfloor \sum_{d|T} \mu(d) f(\frac{T}{d}) \\ \end{align} $$

考虑\(g(n) = \sum_{i|n} \mu(i) f(\frac{n}{i})\)
\(S = \\{ p_i \\}\)\(p_i\)\(n\)的质因子,则只有当\(i=\prod_{j \in S' \subseteq S} j\)时才对\(g(n)\)有贡献。
\(A \subseteq S\)表示指数最大(假设为\(y\))的质因子集合,\(B=S-A\)。则\(i\)可以看做从\(A\)中选出一些质因子再从\(B\)中选出一些质因子组合一下。
由于\(f(\frac{n}{i})\)的取值只取决于\(i\)中从\(A\)集合取的子集(可以发现\(f\)要么是\(a\),要么是\(a-1\),由\(A\)来决定的),所以我们只需考虑\(A\)的子集。
\(B \neq \varnothing\)时,当选的\(A\)的子集确定后即\(f(\frac{n}{i})\)相同时,由于从\(B\)中奇偶大小子集的个数相同,因此奇数个质因子的\(i\)和偶数个质因子的\(i\)的个数相同,所以\(\mu(i)\)的和为\(0\)。所以\(g(n)=0\)
\(B = \varnothing\)时,则只有当\(i=\prod_{j \in S} j\)\(f(\frac{n}{i})=y-1\),否则\(f(\frac{n}{i})=y\)。而当\(f(\frac{n}{i})=y\)时,对于这个非全集的所有子集,奇数大小的子集和偶数大小的子集个数相差为1,计算一下就知道这种情况的贡献是\((-1)^{|S|+1} a\)。对于全集,贡献是\((-1)^{|S|} (a-1)\)。所以\(g(n) = (-1)^{|S|} (a-1) + (-1)^{|S|+1} a = (-1)^{|S|+1}\)

于是线性筛筛出\(g(n)\)即可。

题解

至于查询,分块就行了。
复杂度\(O(b+Tb^{0.5})\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Lim=10000005;
int N, x[10005], y[10005], f[Lim], p[Lim], mu[Lim], cnt;
bool np[Lim];
ll sum[Lim];
void init() {
	mu[1]=1;
	for(int i=2; i<=N; ++i) {
		if(!np[i]) p[cnt++]=i, mu[i]=-1;
		for(int j=0; j<cnt; ++j) {
			int t=p[j]*i; if(t>N) break;
			np[t]=1;
			if(i%p[j]==0) break;
			mu[t]=-mu[i];
		}
	}
	for(int i=2; i<=N; ++i) {
		if(mu[i]) {
			sum[i]=-mu[i];
		}
	}
	for(int i=N; i>=2; --i) {
		if(sum[i]) {
			for(ll j=(ll)i*i; j<=N; j*=i) {
				sum[j]=sum[i];
			}
		}
	}
	for(int i=2; i<=N; ++i) {
		sum[i]+=sum[i-1];
	}
}
int main() {
	int T; scanf("%d", &T);
	for(int i=1; i<=T; ++i) scanf("%d%d", &x[i], &y[i]), N=max(N, x[i]), N=max(N, y[i]);
	init();
	for(int tt=1; tt<=T; ++tt) {
		int a=x[tt], b=y[tt];
		if(a>b) swap(a, b);
		int now=1;
		ll ans=0;
		for(int i=1; i<=a; i=now+1) {
			now=min(a/(a/i), b/(b/i));
			ans+=(ll)(a/i)*(ll)(b/i)*(sum[now]-sum[i-1]);
		}
		printf("%lld\n", ans);
	}
	return 0;
}
posted @ 2015-11-22 14:35  iwtwiioi  阅读(482)  评论(0编辑  收藏  举报