由于是没有质量的垃圾博客,就直接放 csdn 了。
对于一个积性函数 f ( n ) f(n) f(n),我们的目标是求出 S ( n ) = ∑ f ( i ) S(n)=\sum f(i) S(n)=∑f(i),我们选择构造积性函数 g ( n ) g(n) g(n),并以 g ( 1 ) S ( n ) g(1)S(n) g(1)S(n) 的形式间接求出 S ( n ) S(n) S(n)(内心 p.s. 这么 constructive 的东西怎么发明的)。
我们把 Dirichlet Convolution 的形式略改一下, ∑ i = 1 n ( f ∗ g ) ( i ) = ∑ i = 1 n ∑ d ∣ i f ( d ) × g ( i d ) = ∑ d = 1 n f ( d ) ∑ i = 1 n / d g ( i ) = \displaystyle\sum_{i=1}^n(f\ast g)(i)=\sum_{i=1}^n\sum_{d\mid i}f(d)\times g(\frac{i}{d})=\sum_{d=1}^nf(d)\sum_{i=1}^{n/d}g(i)= i=1∑n(f∗g)(i)=i=1∑nd∣i∑f(d)×g(di)=d=1∑nf(d)i=1∑n/dg(i)=,带入 g g g 和 S S S 得 ∑ i = 1 n ∑ d ∣ i g ( d ) f ( i d ) = ∑ i = 1 n g ( i ) S ( n / i ) \displaystyle\sum_{i=1}^n\sum_{d\mid i}g(d)f\left(\frac{i}{d}\right)=\sum_{i=1}^ng(i)S(n/i) i=1∑nd∣i∑g(d)f(di)=i=1∑ng(i)S(n/i)。
于是 g ( 1 ) S ( n ) = ( ∑ i = 1 n ( f ∗ g ) ( i ) ) − ( ∑ i = 2 n g ( i ) S ( n / i ) ) \displaystyle g(1)S(n)=\left(\sum_{i=1}^n(f\ast g)(i)\right)-\left(\sum_{i=2}^ng(i)S(n/i)\right) g(1)S(n)=(i=1∑n(f∗g)(i))−(i=2∑ng(i)S(n/i))。
直接看题捏。
51nod 1227 平均最小公倍数
给定 a , b a,b a,b,求 ∑ i = a b ∑ j = 1 i j ( i , j ) \displaystyle\sum_{i=a}^b\sum_{j=1}^i\frac{j}{(i,j)} i=a∑bj=1∑i(i,j)j
1 ⩽ a , b ⩽ 1 0 9 1\leqslant a,b\leqslant10^9 1⩽a,b⩽109
考虑前缀答案,容易化成 ∑ d = 1 n ∑ i = 1 n / d ∑ j = 1 i j [ ( i , j ) = 1 ] \displaystyle\sum_{d=1}^n\sum_{i=1}^{n/d}\sum_{j=1}^ij[(i,j)=1] d=1∑ni=1∑n/dj=1∑ij[(i,j)=1],于是我们考虑求 f ( n ) f(n) f(n) = 与小于 n n n 且与其互质的数之和。
于是有, f ( n ) = ∑ i = 1 n i [ ( i , n ) = 1 ] = ∑ i = 1 n i ∑ k ∣ ( i , n ) μ ( k ) = ∑ k ∣ n μ ( k ) × k ∑ i = 1 n / k i = n 2 ( ( ∑ k ∣ n μ ( k ) × n / k ) + ( ∑ k ∣ n μ ( k ) ) ) = n 2 ( φ ( n ) + ϵ ( n ) ) \displaystyle f(n)=\sum_{i=1}^n i[(i,n)=1]=\sum_{i=1}^n i\sum_{k\mid(i,n)}\mu(k)=\sum_{k\mid n}\mu(k)\times k\sum_{i=1}^{n/k}i=\frac{n}{2}\left(\left(\sum_{k\mid n}\mu(k)\times n/k\right)+\left(\sum_{k\mid n}\mu(k)\right)\right)=\frac{n}{2}(\varphi(n)+\epsilon(n)) f(n)=i=1∑ni[(i,n)=1]=i=1∑nik∣(i,n)∑μ(k)=k∣n∑μ(k)×ki=1∑n/ki=2n⎝⎛⎝⎛k∣n∑μ(k)×n/k⎠⎞+⎝⎛k∣n∑μ(k)⎠⎞⎠⎞=2n(φ(n)+ϵ(n))。
于是原式可化为 n 2 + 1 2 ( ∑ d = 1 n ∑ i = 1 n / d i × φ ( i ) ) \displaystyle\frac{n}{2}+\frac{1}{2}\left(\sum_{d=1}^n\sum_{i=1}^{n/d}i\times\varphi(i)\right) 2n+21⎝⎛d=1∑ni=1∑n/di×φ(i)⎠⎞,观察到 id ( i ) ∗ i × φ ( i ) = ∑ d ∣ i φ ( i ) × i / d = i 2 \displaystyle\textit{id}(i)\ast i\times\varphi(i)=\sum_{d\mid i}\varphi(i)\times i/d=i^2 id(i)∗i×φ(i)=d∣i∑φ(i)×i/d=i2,套一个二次方和公式即可杜教筛了。logical & reasonable!
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define cmin(x, ...) x = min({x, __VA_ARGS__})
#define cmax(x, ...) x = max({x, __VA_ARGS__})
#define fors(i, l, r, ...) for(int i = (l), REP##i = (r), ##__VA_ARGS__; i <= REP##i; ++i)
#define dfors(i, r, l, ...) for(int i = (r), REP##i = (l), ##__VA_ARGS__; i >= REP##i; --i)
const int P = 1e9+7;
struct custom_hash {
static uint64_t splitmix64(uint64_t x) {
x += 0x9e3779b97f4a7c15;
x = (x^(x>>30))*0xbf58476d1ce4e5b9;
x = (x^(x>>27))*0x94d049bb133111eb;
return x^(x>>31);
}
size_t operator()(uint64_t x) const {
static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x+FIXED_RANDOM);
}
};
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
// f(n) = sum(1~n) i*phi(i)
// id*f = sum(1~n) i^2
// S(n) = sum(1~n) i^2 - sum(2~n) S(n/i)*i
const function<int(const ll)> p_f = [&](const ll x) {
static const ll THRESHOLD = 1e7;
static unordered_map<ll, int, custom_hash> g_f;
static auto l_f = [&](const int n) {
vector<int> f(n+1), prime;
vector<bool> not_prime(n+1);
f[1] = 1;
fors(i, 2, n) {
if(not_prime[i] == 0) f[i] = i-1,prime.emplace_back(i);
for(const int p : prime) {
if(i > n/p) break;
not_prime[i*p] = 1;
if(i%p == 0) {
f[i*p] = ll(f[i])*p%P;
break;
}
f[i*p] = ll(f[i])*f[p]%P;
}
}
fors(i, 1, n) f[i] = (f[i-1]+ll(f[i])*i%P)%P;
return f;
}(THRESHOLD);
if(x <= THRESHOLD) return l_f[x];
if(g_f.count(x)) return g_f[x];
int _x = x%P, res = ll(_x)*((2*_x+1)%P)%P*(_x+1)%P*166666668%P; // sum(1~n) i^2
for(ll l = 2, r; l <= x; l = r+1) {
r = x/(x/l);
res -= (ll)p_f(x/l)*(r-l+1)%P*(l+r)%P*(P+1)/2%P, res %= P;
}
return g_f[x] = (res+P)%P;
};
auto cal = [&](const ll x) {
int res = x;
for(ll l = 1, r; l <= x; l = r+1) {
r = x/(x/l);
res += (ll)p_f(x/l)*(r-l+1)%P, res %= P;
}
(res += P) %= P;
return ll(res)*(P+1)/2%P;
};
ll a, b; cin >> a >> b;
cout << (cal(b)-cal(a-1)+P)%P << "\n";
return 0;
}