【学习笔记】杜教筛

1.莫比乌斯求和

ϵ ( n ) = { 1 , n = 1 0 , n ≠ 1 I ( n ) = 1 ϵ ( n ) = ∑ i ∣ n μ ( i ) × I ( n i ) ∑ i = 1 n ϵ ( i ) = ∑ i = 1 n ∑ d ∣ i μ ( d ) × I ( i d ) = ∑ i = 1 n I ( i ) × Q ( ⌊ n i ⌋ ) I ( 1 ) × Q ( n ) = ∑ i = 1 n ϵ ( i ) − ∑ i = 2 n I ( i ) × Q ( ⌊ n i ⌋ ) \begin{aligned} \epsilon (n) &= \begin{cases} 1, n = 1\\0,n \neq 1 \end{cases} \\ I (n) &= 1 \\ \epsilon (n) &= \sum_{i \mid n} \mu (i) \times I (\frac{n}{i}) \\ \sum_{i = 1}^{n} \epsilon (i) &= \sum_{i = 1}^{n} \sum_{d \mid i} \mu (d) \times I (\frac{i}{d}) \\ &= \sum_{i = 1}^{n} I (i) \times Q (\lfloor \frac{n}{i} \rfloor) \\ I (1) \times Q (n) &= \sum_{i = 1}^{n} \epsilon (i) - \sum_{i = 2}^{n} I (i) \times Q (\lfloor \frac{n}{i} \rfloor) \end{aligned} ϵ(n)I(n)ϵ(n)i=1nϵ(i)I(1)×Q(n)={1,n=10,n=1=1=inμ(i)×I(in)=i=1ndiμ(d)×I(di)=i=1nI(i)×Q(in)=i=1nϵ(i)i=2nI(i)×Q(in)

#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstdlib> 
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define fi first
#define se second
#define db double
#define LL long long
#define ULL unsigned long long
#define PII pair <int, int>
#define MP(x,y) make_pair (x, y)
#define rep(i,j,k) for (int i = (j); i <= (k); ++i)
#define per(i,j,k) for (int i = (j); i >= (k); --i)

template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return x > 0 ? x : -x; }
template <typename T>
void read (T &x) {
    x = 0; T f = 1;
    char ch = getchar ();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar ();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + ch - '0';
        ch = getchar ();
    }
    x *= f;
}
template <typename T, typename... Args>
void read (T &x, Args&... args) {
    read (x); read (args...);
}
char For_Print[25];
template <typename T>
void write (T x) {
    if (x == 0) { putchar ('0'); return; }
    if (x < 0) { putchar ('-'); x = -x; }
    int poi = 0;
    while (x) {
        For_Print[++poi] = x % 10 + '0';
        x /= 10;
    }
    while (poi) putchar (For_Print[poi--]);
}
template <typename T>
void print (T x, char ch) {
    write (x); putchar (ch);
}

const LL Mod = 1e9 + 7;

LL square (LL x) { return (x * x) % Mod; }
void DEL (LL &x, LL y) { ((x -= y) < 0) && (x += Mod); }
void ADD (LL &x, LL y) { ((x += y) >= Mod) && (x -= Mod); }

const int Maxn = 1e6;

LL t, l, r;

bool vis[Maxn + 5];
int cnt, primes[Maxn + 5];
int mu[Maxn + 5], pre[Maxn + 5];
void Euler () {
	mu[1] = 1;
	for (int i = 2; i <= Maxn; i++) {
		if (vis[i] == 0) {
			primes[++cnt] = i;
			mu[i] = -1;
		}
		rep (j, 1, cnt) {
			if (primes[j] > Maxn / i) break;
			vis[i * primes[j]] = 1;
			if (i % primes[j] == 0) {
				mu[i * primes[j]] = 0;
				break;
			}
			mu[i * primes[j]] = -mu[i];
		}
	}
	rep (i, 1, Maxn) {
		pre[i] = pre[i - 1] + mu[i];
	}
}
map <LL, int> dp;
LL Calc (LL n) {
	if (n <= Maxn) return pre[n];
	if (dp.find (n) != dp.end ()) return dp[n];
	LL l = 2, r, res = 1;
	while (l <= n) {
		r = (n / (n / l));
		res -= (r - l + 1) * Calc (n / l);
		l = r + 1;
	}
	return dp[n] = res;
}

int main () {
//	freopen ("D:\\lihan\\1.in", "r", stdin);
//	freopen ("D:\\lihan\\1.out", "w", stdout);

	Euler ();

	read (l, r);
	cout << Calc (r) - Calc (l - 1) << endl;
    return 0;
}

2.欧拉函数求和

i d ( n ) = ∑ d ∣ n φ ( d ) ∑ i = 1 n i d ( i ) = ∑ i = 1 n ∑ d ∣ i φ ( d ) = ∑ i = 1 n ∑ d ∣ i φ ( d ) I ( n d ) = ∑ i = 1 n I ( i ) Q ( ⌊ n i ⌋ ) I ( 1 ) Q ( n ) = ∑ i = 1 n i d ( i ) − ∑ i = 2 n I ( i ) Q ( ⌊ n i ⌋ ) \begin{aligned} id (n) &= \sum_{d \mid n} \varphi (d) \\ \sum_{i = 1}^{n} id (i) &= \sum_{i = 1} ^ {n} \sum_{d \mid i} \varphi (d) \\ &= \sum_{i = 1}^{n} \sum_{d \mid i} \varphi (d) I (\frac{n}{d}) \\ &= \sum_{i = 1}^{n} I (i) Q (\lfloor \frac{n}{i} \rfloor) \\ I (1) Q (n) &= \sum_{i = 1} ^{n}id (i) - \sum_{i = 2}^{n} I (i) Q (\lfloor \frac{n}{i} \rfloor) \end{aligned} id(n)i=1nid(i)I(1)Q(n)=dnφ(d)=i=1ndiφ(d)=i=1ndiφ(d)I(dn)=i=1nI(i)Q(in)=i=1nid(i)i=2nI(i)Q(in)

#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstdlib> 
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define fi first
#define se second
#define db double
#define LL long long
#define ULL unsigned long long
#define PII pair <int, int>
#define MP(x,y) make_pair (x, y)
#define rep(i,j,k) for (int i = (j); i <= (k); ++i)
#define per(i,j,k) for (int i = (j); i >= (k); --i)

template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return x > 0 ? x : -x; }
template <typename T>
void read (T &x) {
    x = 0; T f = 1;
    char ch = getchar ();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar ();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + ch - '0';
        ch = getchar ();
    }
    x *= f;
}
template <typename T, typename... Args>
void read (T &x, Args&... args) {
    read (x); read (args...);
}
char For_Print[25];
template <typename T>
void write (T x) {
    if (x == 0) { putchar ('0'); return; }
    if (x < 0) { putchar ('-'); x = -x; }
    int poi = 0;
    while (x) {
        For_Print[++poi] = x % 10 + '0';
        x /= 10;
    }
    while (poi) putchar (For_Print[poi--]);
}
template <typename T>
void print (T x, char ch) {
    write (x); putchar (ch);
}

const int Maxn = 1e6;
const LL Mod = 1000000007;

LL m;

bool vis[Maxn + 5];
int cnt, primes[Maxn + 5];
LL varphi[Maxn + 5], pre[Maxn + 5];
void Euler () {
	varphi[1] = 1;
	for (int i = 2; i <= Maxn; i++) {
		if (vis[i] == 0) {
			primes[++cnt] = i;
			varphi[i] = i - 1;
		}
		rep (j, 1, cnt) {
			if (primes[j] > Maxn / i) break;
			vis[i * primes[j]] = 1;
			if (i % primes[j] == 0) {
				varphi[i * primes[j]] = varphi[i] * primes[j];
				break;
			}
			varphi[i * primes[j]] = varphi[i] * (primes[j] - 1);
		}
	}
	rep (i, 1, Maxn) {
		pre[i] = pre[i - 1] + varphi[i];
		pre[i] %= Mod;
	}
}
map <LL, LL> dp;
LL Calc (LL n) {
	if (n <= Maxn) return pre[n];
	if (dp.find (n) != dp.end ()) return dp[n];
	LL l = 2, r, res = ((n % Mod) * ((n + 1) % Mod) / 2) % Mod;
	while (l <= n) {
		r = (n / (n / l));
		res = (res - Calc (n / l) * ((r - l + 1) % Mod) % Mod + Mod) % Mod;
		l = r + 1;
	}
	return dp[n] = res;
}

int main () {
//	freopen ("D:\\lihan\\1.in", "r", stdin);
//	freopen ("D:\\lihan\\1.out", "w", stdout);

	Euler ();

	read (m);
	write (Calc (m));
    return 0;
}

3.欧拉函数乘上 i d id id

Q ( i ) = ∑ i = 1 n i × φ ( i ) ( Q ∗ i d ) ( n ) = ∑ d ∣ n i × φ ( i ) × i d ( n i ) = ∑ d ∣ n φ ( i ) × n = n × n ∑ i = 1 n i 2 = ∑ i = 1 n ∑ d ∣ i d × φ ( d ) × i d ( i d ) = ∑ i = 1 n i d ( i ) × Q ( ⌊ n i ⌋ ) Q ( n ) = ∑ i = 1 n i 2 − ∑ i = 2 n i d ( i ) × Q ( ⌊ n i ⌋ ) \begin{aligned} Q (i) &= \sum_{i = 1}^{n} i \times \varphi (i) \\ (Q * id) (n) &= \sum_{d \mid n} i \times \varphi (i) \times id (\frac{n}{i}) \\ &= \sum_{d \mid n} \varphi (i) \times n \\ &= n \times n \\ \sum_{i =1}^{n} i^2 &= \sum_{i = 1}^{n} \sum_{d \mid i} d \times \varphi (d) \times id (\frac{i}{d}) \\ &= \sum_{i = 1}^{n} id (i) \times Q (\lfloor \frac{n}{i} \rfloor) \\ Q (n) &= \sum_{i = 1} ^{n} i^2 - \sum_{i = 2}^{n} id (i) \times Q (\lfloor \frac{n}{i} \rfloor) \end{aligned} Q(i)(Qid)(n)i=1ni2Q(n)=i=1ni×φ(i)=dni×φ(i)×id(in)=dnφ(i)×n=n×n=i=1ndid×φ(d)×id(di)=i=1nid(i)×Q(in)=i=1ni2i=2nid(i)×Q(in)


4.数论函数求和

∑ d ∣ n f ( d ) = n 2 − 3 n + 2 Q ( n ) = ∑ i = 1 n f ( i ) ∑ i = 1 n ( i 2 − 3 i + 2 ) = ∑ i = 1 n ∑ d ∣ i f ( d ) I ( n d ) = ∑ i = 1 n I ( i ) × Q ( ⌊ n i ⌋ ) Q ( n ) = ∑ i = 1 ( i 2 − 3 i + 2 ) − ∑ i = 2 n I ( i ) × Q ( ⌊ n i ⌋ ) \begin{aligned} \sum_{d \mid n} f (d) &= n ^ 2 - 3n + 2 \\ Q(n) &= \sum_{i = 1}^{n} f (i) \\ \sum_{i = 1}^{n} (i^2 - 3i + 2) &= \sum_{i = 1}^{n} \sum_{d \mid i} f (d) I (\frac{n}{d}) \\ &= \sum_{i = 1}^{n} I (i) \times Q (\lfloor \frac{n}{i} \rfloor) \\ Q (n) &= \sum_{i = 1}(i ^ 2 - 3i + 2) - \sum_{i = 2}^{n} I (i) \times Q (\lfloor \frac{n}{i} \rfloor) \end{aligned} dnf(d)Q(n)i=1n(i23i+2)Q(n)=n23n+2=i=1nf(i)=i=1ndif(d)I(dn)=i=1nI(i)×Q(in)=i=1(i23i+2)i=2nI(i)×Q(in)


5.平均最小公倍数

引理 1 1 1:

∑ i = 1 n l c m ( i , n ) n = 1 + ∑ d ∣ n φ ( d ) d 2 \sum_{i = 1}^{n} \frac{lcm (i, n)}{n} = \frac{1 + \sum_{d \mid n} \varphi (d)d}{2} i=1nnlcm(i,n)=21+dnφ(d)d

证明:

∑ i = 1 n l c m ( i , n ) n = ∑ g = 1 n ∑ i = 1 n i × n g × n [ g = g c d ( i , n ) ] = ∑ g = 1 n ∑ i = 1 n i g ⋅ [ g = g c d ( i , n ) ] = ∑ g ∣ n ∑ i = 1 n i g ⋅ [ g = g c d ( i , n ) ] = ∑ g ∣ n ∑ i = 1 n i g ⋅ [ g = g c d ( i , n ) ] \begin{aligned} \sum_{i = 1}^{n} \frac{lcm (i, n)}{n} &= \sum_{g = 1}^{n} \sum_{i = 1}^{n} \frac{i \times n}{g \times n} [g = gcd (i, n)] \\ &= \sum_{g = 1}^{n} \sum_{i = 1}^{n} \frac{i}{g} \cdot [g = gcd (i, n)] \\ &= \sum_{g \mid n} \sum_{i = 1}^{n} \frac{i}{g} \cdot [g = gcd (i, n)] \\ &= \sum_{g \mid n} \sum_{i = 1}^{n} \frac{i}{g} \cdot [g = gcd (i, n)] \end{aligned} i=1nnlcm(i,n)=g=1ni=1ng×ni×n[g=gcd(i,n)]=g=1ni=1ngi[g=gcd(i,n)]=gni=1ngi[g=gcd(i,n)]=gni=1ngi[g=gcd(i,n)]


Q ( n ) = ∑ i = 1 n ∑ j = 1 i l c m ( i , j ) i Q ( n ) = ∑ i = 1 n 1 + ∑ d ∣ i φ ( d ) d 2 ( 引 理 ) Q ( n ) = 1 2 ( ∑ i = 1 n ∑ d ∣ i φ ( d ) d ) + n 2 即 求 ∑ i = 1 n ∑ d ∣ i φ ( d ) d ∑ i = 1 n ∑ d ∣ i φ ( d ) d = ∑ i = 1 n φ ( i ) × i × ⌊ n i ⌋ 数 论 分 块 , 即 求 ( ∑ i = l r φ ( i ) × i ) × ⌊ n l ⌋ ( 用 3. ) \begin{aligned} Q (n) &= \sum_{i = 1}^{n} \sum_{j = 1}^{i} \frac{lcm (i, j)}{i} \\ Q (n) &= \sum_{i = 1}^{n} \frac{1 + \sum_{d \mid i} \varphi (d)d}{2} (引理) \\ Q (n) &= \frac{1}{2}(\sum_{i= 1}^{n} \sum_{d \mid i} \varphi (d) d) + \frac{n}{2} \\ 即求& \sum_{i= 1}^{n} \sum_{d \mid i} \varphi (d) d \\ \sum_{i= 1}^{n} \sum_{d \mid i} \varphi (d) d &= \sum_{i = 1}^{n} \varphi (i) \times i \times \lfloor \frac{n}{i} \rfloor \\ 数论&分块,即求 (\sum_{i = l}^{r} \varphi (i) \times i) \times \lfloor \frac{n}{l} \rfloor (用 3.) \end{aligned} Q(n)Q(n)Q(n)i=1ndiφ(d)d=i=1nj=1iilcm(i,j)=i=1n21+diφ(d)d()=21(i=1ndiφ(d)d)+2ni=1ndiφ(d)d=i=1nφ(i)×i×in(i=lrφ(i)×i)×ln3.

外面套了一个数论分块,似乎时间复杂度是 O ( n 1 2 ⋅ n 1 2 ) = O ( n ) O (n^{\frac{1}{2}} \cdot n^{\frac{1}{2}}) = O (n) O(n21n21)=O(n)

但是询问的 m m m 都是满足 ∃ i , ⌊ n i ⌋ \exists i, \lfloor \frac{n}{i} \rfloor i,in,所以询问不会超过 ( n ) \sqrt (n) ( n) 个。

所以时间复杂度还是没变。

#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstdlib> 
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define fi first
#define se second
#define db double
#define LL long long
#define ULL unsigned long long
#define PII pair <int, int>
#define MP(x,y) make_pair (x, y)
#define rep(i,j,k) for (int i = (j); i <= (k); ++i)
#define per(i,j,k) for (int i = (j); i >= (k); --i)

template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return x > 0 ? x : -x; }
template <typename T>
void read (T &x) {
    x = 0; T f = 1;
    char ch = getchar ();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar ();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + ch - '0';
        ch = getchar ();
    }
    x *= f;
}
template <typename T, typename... Args>
void read (T &x, Args&... args) {
    read (x); read (args...);
}
char For_Print[25];
template <typename T>
void write (T x) {
    if (x == 0) { putchar ('0'); return; }
    if (x < 0) { putchar ('-'); x = -x; }
    int poi = 0;
    while (x) {
        For_Print[++poi] = x % 10 + '0';
        x /= 10;
    }
    while (poi) putchar (For_Print[poi--]);
}
template <typename T>
void print (T x, char ch) {
    write (x); putchar (ch);
}

const int Maxn = 1e6;
const LL Mod = 1000000007;

LL md (LL x, LL M) {
	return (x % M + M) % M;
}

LL inv_2, inv_6;

LL quick_pow (LL x, LL y) {
	LL res = 1;
	while (y) {
		if (y & 1) res = md (res * x, Mod);
		x = md (x * x, Mod); y >>= 1;
	}
	return res;
}
bool vis[Maxn + 5];
int cnt, primes[Maxn + 5];
LL phi[Maxn + 5], pre[Maxn + 5];
void Euler () {
	phi[1] = 1;
	for (int i = 2; i <= Maxn; i++) {
		if (vis[i] == 0) {
			primes[++cnt] = i;
			phi[i] = i - 1;
		}
		rep (j, 1, cnt) {
			if (primes[j] > Maxn / i) break;
			vis[i * primes[j]] = 1;
			if (i % primes[j] == 0) {
				phi[i * primes[j]] = phi[i] * primes[j];
				break;
			}
			phi[i * primes[j]] = phi[i] * (primes[j] - 1);
		}
	}
	rep (i, 1, Maxn) {
		pre[i] = pre[i - 1] + md (phi[i] * i, Mod);
		pre[i] %= Mod;
	}
}
map <LL, LL> dp;
LL Calc (LL n) {
	if (n <= Maxn) return pre[n];
	if (dp.find (n) != dp.end ()) return dp[n];
	LL l = 2, r, res = md (md (n, Mod) * md (md (n + 1, Mod) * md (md (2 * n + 1, Mod) * inv_6, Mod), Mod), Mod);
	while (l <= n) {
		r = (n / (n / l));
		res = md (res - md (Calc (n / l) * md (md (l + r, Mod) * md (md (r - l + 1, Mod) * inv_2, Mod), Mod), Mod), Mod);
		l = r + 1;
	}
	return dp[n] = res;
}
LL Query (LL n) {
	LL l = 1, r, res = 0;
	while (l <= n) {
		r = n / (n / l);
		res = md (res + md (Calc (r) - Calc (l - 1), Mod) * (n / l), Mod);
		l = r + 1;
	}
	res = md (res * inv_2, Mod);
	res = md (res + md (n * inv_2, Mod), Mod);
	return res;
}

int main () {
//	freopen ("D:\\lihan\\1.in", "r", stdin);
//	freopen ("D:\\lihan\\1.out", "w", stdout);

	Euler ();
	
	inv_2 = quick_pow (2, Mod - 2);
	inv_6 = quick_pow (6, Mod - 2);
	LL l, r; cin >> l >> r;
	cout << md (Query (r) - Query (l - 1), Mod);
    return 0;
}

6.Lucas的数论

引理:

∑ d ∣ i j 1 ( d ) = ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] \sum_{d \mid ij} 1 (d) = \sum_{x \mid i} \sum_{y \mid j} [gcd (x, y) = 1] dij1(d)=xiyj[gcd(x,y)=1]

算二次证明。

相当于我们枚举的因数为: i x ⋅ y \frac{i}{x} \cdot y xiy

不漏:

每个 i j ij ij 的因数都应该是枚举得到的,不用哆嗦。

不重:

相当于我们的 x x x 会从 i i i 处刮掉一些因子,而 y y y 会在 j j j 中取一些因子, g c d ( x , y ) = 1 gcd (x, y) = 1 gcd(x,y)=1 就防止了从 i i i 处刮掉的因子和从 j j j 处取得的因子出现重复,就不会算重了。


∑ i = 1 n ∑ j = 1 n f ( i j ) = ∑ i = 1 n ∑ j = 1 n ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] = ∑ i = 1 n ∑ j = 1 n ∑ x ∣ i ∑ y ∣ j ∑ t ∣ g c d ( x , y ) μ ( t ) = ∑ x = 1 n ∑ y = 1 n ∑ x ∣ i n ∑ y ∣ j n ∑ t ∣ g c d ( x , y ) μ ( t ) = ∑ x = 1 n ∑ y = 1 n ⌊ n x ⌋ ⌊ n y ⌋ ∑ t ∣ g c d ( x , y ) μ ( t ) = ∑ t = 1 n μ ( t ) ∑ t ∣ x ⌊ n x ⌋ ∑ t ∣ y ⌊ n y ⌋ = ∑ t = 1 n μ ( t ) ∑ x = 1 ⌊ n t ⌋ ⌊ ⌊ n t ⌋ x ⌋ ∑ y = 1 ⌊ n t ⌋ ⌊ ⌊ n t ⌋ y ⌋ 令 f ( n ) = ∑ i = 1 n ⌊ n i ⌋ 原 式 = ∑ t = 1 n μ ( t ) f ( ⌊ n t ⌋ ) f ( ⌊ n t ⌋ ) \begin{aligned} \sum_{i = 1}^{n} \sum_{j = 1}^{n} f (ij) &= \sum_{i = 1}^{n} \sum_{j = 1}^{n} \sum_{x \mid i} \sum_{y \mid j} [gcd (x, y) = 1] \\ &= \sum_{i = 1}^{n} \sum_{j = 1}^{n} \sum_{x \mid i} \sum_{y \mid j} \sum_{t \mid gcd (x, y)} \mu (t) \\ &= \sum_{x = 1}^{n} \sum_{y = 1}^{n} \sum_{x \mid i}^{n} \sum_{y \mid j}^{n} \sum_{t \mid gcd (x, y)} \mu (t) \\ &= \sum_{x = 1}^{n} \sum_{y = 1}^{n} \lfloor \frac{n}{x} \rfloor \lfloor \frac{n}{y} \rfloor \sum_{t \mid gcd (x, y)} \mu (t) \\ &= \sum_{t = 1}^{n} \mu (t) \sum_{t \mid x} \lfloor \frac{n}{x} \rfloor \sum_{t \mid y} \lfloor \frac{n}{y} \rfloor \\ &= \sum_{t = 1}^{n} \mu (t) \sum_{x = 1}^{\lfloor \frac{n}{t} \rfloor} \lfloor \frac{\lfloor \frac{n}{t} \rfloor}{x} \rfloor \sum_{y = 1}^{\lfloor \frac{n}{t} \rfloor} \lfloor \frac{\lfloor \frac{n}{t} \rfloor}{y} \rfloor \\ 令 f (n) &= \sum_{i = 1}^{n} \lfloor \frac{n}{i} \rfloor \\ 原式 &= \sum_{t = 1}^{n} \mu (t) f (\lfloor \frac{n}{t} \rfloor) f (\lfloor \frac{n}{t} \rfloor) \end{aligned} i=1nj=1nf(ij)f(n)=i=1nj=1nxiyj[gcd(x,y)=1]=i=1nj=1nxiyjtgcd(x,y)μ(t)=x=1ny=1nxinyjntgcd(x,y)μ(t)=x=1ny=1nxnyntgcd(x,y)μ(t)=t=1nμ(t)txxntyyn=t=1nμ(t)x=1tnxtny=1tnytn=i=1nin=t=1nμ(t)f(tn)f(tn)

在外面一个数论分块, f ( ⌊ n t ⌋ ) f (\lfloor \frac{n}{t} \rfloor) f(tn) 可以直接暴力求(根据杜教筛的时间复杂度理论),然后 μ ( t ) \mu (t) μ(t) 求和直接用杜教筛就可以啦。

#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstdlib> 
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define fi first
#define se second
#define db double
#define LL long long
#define ULL unsigned long long
#define PII pair <int, int>
#define MP(x,y) make_pair (x, y)
#define rep(i,j,k) for (int i = (j); i <= (k); ++i)
#define per(i,j,k) for (int i = (j); i >= (k); --i)

template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return x > 0 ? x : -x; }
template <typename T>
void read (T &x) {
    x = 0; T f = 1;
    char ch = getchar ();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar ();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + ch - '0';
        ch = getchar ();
    }
    x *= f;
}
template <typename T, typename... Args>
void read (T &x, Args&... args) {
    read (x); read (args...);
}
char For_Print[25];
template <typename T>
void write (T x) {
    if (x == 0) { putchar ('0'); return; }
    if (x < 0) { putchar ('-'); x = -x; }
    int poi = 0;
    while (x) {
        For_Print[++poi] = x % 10 + '0';
        x /= 10;
    }
    while (poi) putchar (For_Print[poi--]);
}
template <typename T>
void print (T x, char ch) {
    write (x); putchar (ch);
}

const int Maxn = 1e6;
const LL Mod = 1000000007;

LL md ( LL x ) {
    return ( x % Mod + Mod ) % Mod;
}

LL t, l, r;

bool vis[Maxn + 5];
int cnt, primes[Maxn + 5];
LL mu[Maxn + 5], pre[Maxn + 5];
void Euler () {
	mu[1] = 1;
	for (int i = 2; i <= Maxn; i++) {
		if (vis[i] == 0) {
			primes[++cnt] = i;
			mu[i] = -1;
		}
		rep (j, 1, cnt) {
			if (primes[j] > Maxn / i) break;
			vis[i * primes[j]] = 1;
			if (i % primes[j] == 0) {
				mu[i * primes[j]] = 0;
				break;
			}
			mu[i * primes[j]] = -mu[i];
		}
	}
	rep (i, 1, Maxn) {
		pre[i] = pre[i - 1] + mu[i];
	}
}
map <LL, LL> dp;
LL Calc (LL n) {
	if (n <= Maxn) return pre[n];
	if (dp.find (n) != dp.end ()) return dp[n];
	LL l = 2, r, res = 1;
	while (l <= n) {
		r = (n / (n / l));
		res = md (res - md ( md (r - l + 1) * md ( Calc ( n / l ) ) ) );
		l = r + 1;
	}
	return dp[n] = res;
}

LL F ( LL x ) {
    LL l = 1, r, res = 0;
    while ( l <= x ) {
        r = x / ( x / l );
        res = md ( res + md ( r - l + 1 ) * md ( x / l ) );
        l = r + 1;
    }
    return res;
}

LL n;

int main () {
	// freopen ( "C:\\Users\\cqbz\\Desktop\\lihan\\1.in", "r", stdin );
	// freopen ( "C:\\Users\\cqbz\\Desktop\\lihan\\1.out", "w", stdout );

	Euler ();

    read ( n );
    Calc ( n );

    LL l = 1, r, res = 0;
    while ( l <= n ) {
        r = n / ( n / l );
        LL tmp = F ( n / l );
        res = md ( res + md ( md ( md ( Calc ( r ) - Calc ( l - 1 ) ) * tmp ) * tmp ) );
        l = r + 1;
    }
    write ( res );
    return 0;
}
7. 约数之和

∑ i = 1 n ∑ j = 1 n f ( i j ) = ∑ i = 1 n ∑ j = 1 n ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] ⋅ i x ⋅ y = ∑ i = 1 n ∑ j = 1 n ∑ x ∣ i ∑ y ∣ j ∑ t ∣ g c d ( x , y ) μ ( t ) ⋅ i x ⋅ y = ∑ x = 1 n ∑ y = 1 n ∑ x ∣ i ∑ y ∣ j ∑ t ∣ x , t ∣ y μ ( t ) ⋅ ( i / x ) ⋅ y = ∑ x = 1 n ∑ y = 1 n ∑ x ∣ i ∑ y ∣ j ∑ t ∣ x , t ∣ y μ ( t ) ⋅ ( i / x ) ⋅ y = ∑ x = 1 n ∑ y = 1 n y ∑ x ∣ i ( i / x ) ∑ y ∣ j ∑ t ∣ x , t ∣ y μ ( t ) = ∑ t μ ( t ) ∑ t ∣ x n ∑ t ∣ y n y ∑ x ∣ i n ( i / x ) ∑ y ∣ j n 1 = ∑ t μ ( t ) ∑ x ⌊ n t ⌋ ∑ y ⌊ n t ⌋ y t ∑ x t ∣ i ( i / x t ) ∑ y t ∣ j 1 = ∑ t μ ( t ) ∑ x ⌊ n t ⌋ ∑ x t ∣ i ( i / x t ) ∑ y ⌊ n t ⌋ y t ∑ y t ∣ j 1 = ∑ t μ ( t ) ∑ x ⌊ n t ⌋ ( 1 + ⌊ ⌊ n t ⌋ x ⌋ ) ∗ ⌊ ⌊ n t ⌋ x ⌋ / 2 ⋅ t ∑ y ⌊ n t ⌋ y ⌊ ⌊ n t ⌋ y ⌋ g ( n ) = ∑ x = 1 n ( 1 + ⌊ n x ⌋ ) ⌊ n x ⌋ / 2 f ( n ) = ∑ x = 1 n ⌊ n x ⌋ x = ∑ t μ ( t ) ⋅ t ⋅ g ( ⌊ n t ⌋ ) ⋅ f ( ⌊ n t ⌋ ) \begin{aligned} \sum_{i = 1}^{n} \sum_{j = 1}^{n} f (ij) &= \sum_{i = 1}^{n} \sum_{j = 1}^{n} \sum_{x \mid i} \sum_{y \mid j} [gcd (x, y) = 1] \cdot \frac{i}{x} \cdot y \\ &= \sum_{i = 1}^{n} \sum_{j = 1}^{n} \sum_{x \mid i} \sum_{y \mid j} \sum_{t \mid gcd (x, y)} \mu (t) \cdot \frac{i}{x} \cdot y \\ &= \sum_{x = 1}^{n} \sum_{y = 1}^{n} \sum_{x \mid i} \sum_{y \mid j} \sum_{t \mid x, t \mid y} \mu ( t) \cdot (i / x) \cdot y \\ &= \sum_{x = 1}^{n} \sum_{y = 1}^{n} \sum_{x \mid i} \sum_{y \mid j} \sum_{t \mid x, t \mid y} \mu ( t) \cdot (i / x) \cdot y \\ &= \sum_{x = 1}^{n} \sum_{y = 1}^{n} y \sum_{x \mid i} (i / x) \sum_{y \mid j} \sum_{t \mid x, t \mid y} \mu ( t) \\ &= \sum_{t} \mu (t) \sum_{t \mid x}^{n} \sum_{t \mid y}^{n} y \sum_{x \mid i}^{n} (i / x) \sum_{y \mid j}^{n} 1 \\ &= \sum_{t} \mu (t) \sum_{x}^{\lfloor \frac{n}{t} \rfloor} \sum_{y}^{\lfloor \frac{n}{t} \rfloor} yt \sum_{xt \mid i} (i / xt) \sum_{yt \mid j} 1 \\ &= \sum_{t} \mu (t) \sum_{x}^{\lfloor \frac{n}{t} \rfloor} \sum_{xt \mid i} (i / xt) \sum_{y}^{\lfloor \frac{n}{t} \rfloor} yt \sum_{yt \mid j} 1 \\ &= \sum_{t} \mu (t) \sum_{x}^{\lfloor \frac{n}{t} \rfloor} (1 + \lfloor \frac{\lfloor \frac{n}{t} \rfloor}{x} \rfloor ) * \lfloor \frac{\lfloor \frac{n}{t} \rfloor}{x} \rfloor / 2 \cdot t \sum_{y}^{\lfloor \frac{n}{t} \rfloor} y \lfloor \frac{\lfloor \frac{n}{t} \rfloor}{y} \rfloor \\ g (n) &= \sum_{x = 1}^{n} (1 + \lfloor \frac{n}{x} \rfloor) \lfloor \frac{n}{x} \rfloor / 2 \\ f (n) &= \sum_{x = 1}^{n} \lfloor \frac{n}{x} \rfloor x \\ &= \sum_{t} \mu (t) \cdot t \cdot g (\lfloor \frac{n}{t} \rfloor) \cdot f (\lfloor \frac{n}{t} \rfloor) \end{aligned} i=1nj=1nf(ij)g(n)f(n)=i=1nj=1nxiyj[gcd(x,y)=1]xiy=i=1nj=1nxiyjtgcd(x,y)μ(t)xiy=x=1ny=1nxiyjtx,tyμ(t)(i/x)y=x=1ny=1nxiyjtx,tyμ(t)(i/x)y=x=1ny=1nyxi(i/x)yjtx,tyμ(t)=tμ(t)txntynyxin(i/x)yjn1=tμ(t)xtnytnytxti(i/xt)ytj1=tμ(t)xtnxti(i/xt)ytnytytj1=tμ(t)xtn(1+xtn)xtn/2tytnyytn=x=1n(1+xn)xn/2=x=1nxnx=tμ(t)tg(tn)f(tn)

这个式子不太好做 😓。

于是大部分做法都是把 i , j i, j i,j x , y x, y x,y 代掉。

∑ i = 1 n ∑ j = 1 n f ( i j ) = ∑ i = 1 n ∑ j = 1 n ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] ⋅ i x ⋅ y = ∑ i = 1 n ∑ j = 1 n ∑ x ∣ i ∑ y ∣ j ∑ t ∣ g c d ( x , y ) μ ( t ) ⋅ i x ⋅ y = ∑ x = 1 n ∑ y = 1 n ∑ x ∣ i ∑ y ∣ j ∑ t ∣ x , t ∣ y μ ( t ) ⋅ ( i / x ) ⋅ y = ∑ x = 1 n ∑ y = 1 n ∑ x ∣ i ∑ y ∣ j ∑ t ∣ x , t ∣ y μ ( t ) ⋅ ( i / x ) ⋅ y = ∑ x = 1 n ∑ y = 1 n y ∑ x ∣ i ( i / x ) ∑ y ∣ j ∑ t ∣ x , t ∣ y μ ( t ) = ∑ t μ ( t ) ∑ t ∣ x n ∑ t ∣ y n y ∑ x ∣ i n ( i / x ) ∑ y ∣ j n 1 = ∑ t μ ( t ) ∑ t ∣ x n ∑ t ∣ y n y ∑ i ⌊ n i ⌋ i ⌊ n y ⌋ \begin{aligned} \sum_{i = 1}^{n} \sum_{j = 1}^{n} f (ij) &= \sum_{i = 1}^{n} \sum_{j = 1}^{n} \sum_{x \mid i} \sum_{y \mid j} [gcd (x, y) = 1] \cdot \frac{i}{x} \cdot y \\ &= \sum_{i = 1}^{n} \sum_{j = 1}^{n} \sum_{x \mid i} \sum_{y \mid j} \sum_{t \mid gcd (x, y)} \mu (t) \cdot \frac{i}{x} \cdot y \\ &= \sum_{x = 1}^{n} \sum_{y = 1}^{n} \sum_{x \mid i} \sum_{y \mid j} \sum_{t \mid x, t \mid y} \mu ( t) \cdot (i / x) \cdot y \\ &= \sum_{x = 1}^{n} \sum_{y = 1}^{n} \sum_{x \mid i} \sum_{y \mid j} \sum_{t \mid x, t \mid y} \mu ( t) \cdot (i / x) \cdot y \\ &= \sum_{x = 1}^{n} \sum_{y = 1}^{n} y \sum_{x \mid i} (i / x) \sum_{y \mid j} \sum_{t \mid x, t \mid y} \mu ( t) \\ &= \sum_{t} \mu (t) \sum_{t \mid x}^{n} \sum_{t \mid y}^{n} y \sum_{x \mid i}^{n} (i / x) \sum_{y \mid j}^{n} 1 \\ &= \sum_{t} \mu (t) \sum_{t \mid x}^{n} \sum_{t \mid y}^{n} y \sum_{i}^{\lfloor \frac{n}{i} \rfloor} i \lfloor \frac{n}{y} \rfloor \end{aligned} i=1nj=1nf(ij)=i=1nj=1nxiyj[gcd(x,y)=1]xiy=i=1nj=1nxiyjtgcd(x,y)μ(t)xiy=x=1ny=1nxiyjtx,tyμ(t)(i/x)y=x=1ny=1nxiyjtx,tyμ(t)(i/x)y=x=1ny=1nyxi(i/x)yjtx,tyμ(t)=tμ(t)txntynyxin(i/x)yjn1=tμ(t)txntynyiiniyn

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值