【18徐州网络赛D】Easy Math

补充一点性质

[sum_{d|n}varphi(d) = n ]

证明

对于 (n = 1) ,不难验证满足题意

对于 (n = p^a) ,

[sum_{d|n}varphi(d) = 1 + sum_{i = 1}^avarphi(p^i) \=p^a = n ]

对于 (n = p_1^{a_1}...p_k^{a_k})

[sum_{d|n}varphi(d) = sum_{i=0}^{a_1}varphi(p_1^i)sum_{i=0}^{a_2}varphi(p_2^i)...sum_{i=0}^{a_k}varphi(p_k^i)\=p_1^{a_1}...p_k^{a_k} = n ]

  • i % p == 0(varphi(i*p) = varphi(i) * p) , (p) 是质数

D. Easy Math

题意

给定 (m,n)

[sum_{i=1}^mmu(i * n) ]

这样就可以进行递归了,但是我不会算复杂度...

还注意到一个地方,线筛的判断 i % prime[j] == 0 的地方要注意函数的取值

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;
typedef long long ll;
ll prime[N], cnt, vis[N], mu[N], sum[N];


void init() {
	mu[1] = 1;
	for (int i = 2; i < N; i++) {
		if (!vis[i]) {
			prime[++cnt] = i;
			mu[i] = -1;
		}
		for (int j = 1; j <= cnt and prime[j] * i < N; j++) {
			vis[prime[j] * i] = 1;
			mu[prime[j] * i] = -mu[i];
			if (i % prime[j] == 0) {
                //**这一行不能去掉**
				mu[i * prime[j]] = 0;
				break;
			}
		}
	}
	for (int i = 1; i < N; i++) sum[i] = sum[i - 1] + mu[i];
}

ll n, m;
unordered_map<ll, ll> M;
ll djs(ll n) {
	if (n < N) return sum[n];
	if (M.count(n)) return M[n];
	ll ans = 1;
	for (ll l = 2, r; l <= n; l = r + 1) {
		r = n / (n / l);
		ans -= (r - l + 1) * djs(n / l);
	}
	return M[n] = ans;
}
ll cal(ll n) {
	int ans = 1;
	if (n < N) return mu[n];
	for (ll i = 2; i * i <= n;i++) {
		if (n % i == 0) {
			if (n % (i * i) == 0)
				return 0;
			ans *= -1;
			n /= i;
		}
	}
	if (n > 1)
		ans *= -1;
	return ans;
}
ll solve(ll m, ll n) {
	if (n == 1) return djs(m);

	ll v = cal(n);
	if (v == 0) return 0;

	ll ans = 0;
	ll t = m < sqrt(n) ? m : sqrt(n);
	for (ll d = 1; d <= t; d++) {
		if (n % d == 0) {
			ans += cal(d) * solve(m / d, d);
			if (n / d <= m)
				ans += cal(n / d) * solve(m / (n / d), n / d);
		}
	}
	return v * ans;
}
int main() {
	init();
	scanf("%lld%lld", &m, &n);
	printf("%lld
", solve(m, n));
}
原文地址:https://www.cnblogs.com/sduwh/p/14048419.html