首先莫比乌斯反演
定理:和都是算术函数,并且满足如下条件:
则有如下结论:
首先我们说一下莫比乌斯函数
1.首先当n=1时,并且表示当n=1时才为1
2.当时,为互异素数时,
3.只要当n含有任何素因子的幂次大于等于2,则函数值为0;
4.
这里从定义上面去证明:
根据定义以及基本运算法则:
稍微思考一下可以得到(d,e)就是(d*e)|n的一个二元组合,因此可以交换两个sum的位置
再结合性质可以得到当e=n时n/e=1因此,就等于g(n)
另外我们做题用得比较多的是另一种形式
这种也简单证明一下首先另k=d/n;
再结合性质可以得到当t=n时t/n=1因此,就等于g(n)
https://vjudge.net/problem/UVALive-4184
http://poj.org/problem?id=3904
题意:给出n个数,问从中选出四个数使得,一共有多少组,a,b,c,d;
做法:这种题一看推公式肯定是莫比乌斯反演,趁热打铁加深一下记忆。
首先令f(n)为表示 其中表示整数倍
然后令g(n)为表示
而f(d)很好求,简单的组合数。
#include "bits/stdc++.h"
using namespace std;
const double eps = 1e-8;
#define reg register
#define lowbit(x) x&-x
#define pll pair<ll,ll>
#define pii pair<int,int>
#define fi first
#define se second
#define makp make_pair
int dcmp(double x) {
if (fabs(x) < eps) return 0;
return (x > 0) ? 1 : -1;
}
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const ull hash2 = 50331653;
const int N = 10000 + 10;
const int M = 1000 + 10;
const int inf = 0x3f3f3f3f;
const ll mod = 998244353;
int vis[N], pri[N], mu[N], cnt, n, tot[N], a[N];
void init() {
vis[1] = mu[1] = 1;
cnt = 0;
for (int i = 2; i < N; i++) {
if (!vis[i]) {
pri[++cnt] = i;
mu[i] = -1;
}
for (int j = 1; j <= cnt && i * pri[j] < N; j++) {
vis[i * pri[j]] = 1;
if (i % pri[j] == 0) break;
mu[i * pri[j]] = -mu[i];
}
}
}
void get_tot() {
memset(tot, 0, sizeof(tot));
for (int i = 1; i <= n; i++) {
for (int j = 1; j * j <= a[i]; j++) {
if (a[i] % j == 0) tot[j]++, tot[a[i] / j]++;
if (j * j == a[i]) tot[j]--;
}
}
}
ll C(int m) {
return 1LL * m * (m - 1) * (m - 2) * (m - 3) / 24;
}
int main() {
init();
while (~scanf("%d", &n)) {
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
get_tot();
ll ans = 0;
for (int i = 1; i < N; i++) {
ans += 1LL * mu[i] * C(tot[i]);
}
printf("%lld\n", ans);
}
return 0;
}