【学习笔记】杜教筛
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=1∑nϵ(i)I(1)×Q(n)={1,n=10,n=1=1=i∣n∑μ(i)×I(in)=i=1∑nd∣i∑μ(d)×I(di)=i=1∑nI(i)×Q(⌊in⌋)=i=1∑nϵ(i)−i=2∑nI(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=1∑nid(i)I(1)Q(n)=d∣n∑φ(d)=i=1∑nd∣i∑φ(d)=i=1∑nd∣i∑φ(d)I(dn)=i=1∑nI(i)Q(⌊in⌋)=i=1∑nid(i)−i=2∑nI(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)(Q∗id)(n)i=1∑ni2Q(n)=i=1∑ni×φ(i)=d∣n∑i×φ(i)×id(in)=d∣n∑φ(i)×n=n×n=i=1∑nd∣i∑d×φ(d)×id(di)=i=1∑nid(i)×Q(⌊in⌋)=i=1∑ni2−i=2∑nid(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} d∣n∑f(d)Q(n)i=1∑n(i2−3i+2)Q(n)=n2−3n+2=i=1∑nf(i)=i=1∑nd∣i∑f(d)I(dn)=i=1∑nI(i)×Q(⌊in⌋)=i=1∑(i2−3i+2)−i=2∑nI(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+∑d∣nφ(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=1∑nnlcm(i,n)=g=1∑ni=1∑ng×ni×n[g=gcd(i,n)]=g=1∑ni=1∑ngi⋅[g=gcd(i,n)]=g∣n∑i=1∑ngi⋅[g=gcd(i,n)]=g∣n∑i=1∑ngi⋅[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=1∑nd∣i∑φ(d)d数论=i=1∑nj=1∑iilcm(i,j)=i=1∑n21+∑d∣iφ(d)d(引理)=21(i=1∑nd∣i∑φ(d)d)+2ni=1∑nd∣i∑φ(d)d=i=1∑nφ(i)×i×⌊in⌋分块,即求(i=l∑rφ(i)×i)×⌊ln⌋(用3.)
外面套了一个数论分块,似乎时间复杂度是 O ( n 1 2 ⋅ n 1 2 ) = O ( n ) O (n^{\frac{1}{2}} \cdot n^{\frac{1}{2}}) = O (n) O(n21⋅n21)=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] d∣ij∑1(d)=x∣i∑y∣j∑[gcd(x,y)=1]
算二次证明。
相当于我们枚举的因数为: i x ⋅ y \frac{i}{x} \cdot y xi⋅y。
不漏:
每个 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=1∑nj=1∑nf(ij)令f(n)原式=i=1∑nj=1∑nx∣i∑y∣j∑[gcd(x,y)=1]=i=1∑nj=1∑nx∣i∑y∣j∑t∣gcd(x,y)∑μ(t)=x=1∑ny=1∑nx∣i∑ny∣j∑nt∣gcd(x,y)∑μ(t)=x=1∑ny=1∑n⌊xn⌋⌊yn⌋t∣gcd(x,y)∑μ(t)=t=1∑nμ(t)t∣x∑⌊xn⌋t∣y∑⌊yn⌋=t=1∑nμ(t)x=1∑⌊tn⌋⌊x⌊tn⌋⌋y=1∑⌊tn⌋⌊y⌊tn⌋⌋=i=1∑n⌊in⌋=t=1∑nμ(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=1∑nj=1∑nf(ij)g(n)f(n)=i=1∑nj=1∑nx∣i∑y∣j∑[gcd(x,y)=1]⋅xi⋅y=i=1∑nj=1∑nx∣i∑y∣j∑t∣gcd(x,y)∑μ(t)⋅xi⋅y=x=1∑ny=1∑nx∣i∑y∣j∑t∣x,t∣y∑μ(t)⋅(i/x)⋅y=x=1∑ny=1∑nx∣i∑y∣j∑t∣x,t∣y∑μ(t)⋅(i/x)⋅y=x=1∑ny=1∑nyx∣i∑(i/x)y∣j∑t∣x,t∣y∑μ(t)=t∑μ(t)t∣x∑nt∣y∑nyx∣i∑n(i/x)y∣j∑n1=t∑μ(t)x∑⌊tn⌋y∑⌊tn⌋ytxt∣i∑(i/xt)yt∣j∑1=t∑μ(t)x∑⌊tn⌋xt∣i∑(i/xt)y∑⌊tn⌋ytyt∣j∑1=t∑μ(t)x∑⌊tn⌋(1+⌊x⌊tn⌋⌋)∗⌊x⌊tn⌋⌋/2⋅ty∑⌊tn⌋y⌊y⌊tn⌋⌋=x=1∑n(1+⌊xn⌋)⌊xn⌋/2=x=1∑n⌊xn⌋x=t∑μ(t)⋅t⋅g(⌊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=1∑nj=1∑nf(ij)=i=1∑nj=1∑nx∣i∑y∣j∑[gcd(x,y)=1]⋅xi⋅y=i=1∑nj=1∑nx∣i∑y∣j∑t∣gcd(x,y)∑μ(t)⋅xi⋅y=x=1∑ny=1∑nx∣i∑y∣j∑t∣x,t∣y∑μ(t)⋅(i/x)⋅y=x=1∑ny=1∑nx∣i∑y∣j∑t∣x,t∣y∑μ(t)⋅(i/x)⋅y=x=1∑ny=1∑nyx∣i∑(i/x)y∣j∑t∣x,t∣y∑μ(t)=t∑μ(t)t∣x∑nt∣y∑nyx∣i∑n(i/x)y∣j∑n1=t∑μ(t)t∣x∑nt∣y∑nyi∑⌊in⌋i⌊yn⌋