题目: 求
∑
i
=
1
n
∑
j
=
1
m
φ
(
i
∗
j
)
\sum_{i = 1}^n\sum_{j = 1} ^ m \varphi(i * j)
∑i=1n∑j=1mφ(i∗j)
解法:
- 我们发现 n n n很小 ,于是考虑枚举 i i i, 于是对于每个 i i i只需要求 ∑ j = 1 m φ ( i ∗ j ) \sum_{j = 1} ^ m \varphi(i * j) ∑j=1mφ(i∗j)
- 设 ω \omega ω为 i i i中所有不同的素因子的乘积, λ λ λ为 i ω \frac{i}{\omega} ωi,于是问题只需要求 λ ∑ j = 1 m φ ( ω ∗ j ) λ\sum_{j = 1} ^ m \varphi(\omega* j) λ∑j=1mφ(ω∗j).
- 设 S ( ω , m ) = ∑ j = 1 m φ ( ω ∗ j ) S(\omega, m) =\sum_{j = 1} ^ m \varphi(\omega* j) S(ω,m)=∑j=1mφ(ω∗j)
- → \rightarrow → S ( ω , m ) = ∑ j = 1 m ( φ ( ω ) φ ( g c d ( ω , j ) ) ) φ ( j ) g c d ( ω , j ) S(\omega, m) =\sum_{j = 1} ^ m (\frac{\varphi(\omega)}{\varphi(gcd(\omega, j))})\varphi(j)gcd(\omega, j) S(ω,m)=∑j=1m(φ(gcd(ω,j))φ(ω))φ(j)gcd(ω,j)
- → \rightarrow → S ( ω , m ) = ∑ j = 1 m φ ( ω g c d ( ω , j ) ) φ ( j ) g c d ( ω , j ) S(\omega, m) =\sum_{j = 1} ^ m \varphi(\frac{\omega}{gcd(\omega, j)})\varphi(j)gcd(\omega, j) S(ω,m)=∑j=1mφ(gcd(ω,j)ω)φ(j)gcd(ω,j)
- → \rightarrow → S ( ω , m ) = ∑ j = 1 m φ ( ω g c d ( ω , j ) ) φ ( j ) ∑ d ∣ g c d ( ω , j ) φ ( d ) S(\omega, m) =\sum_{j = 1} ^ m \varphi(\frac{\omega}{gcd(\omega, j)})\varphi(j)\sum_{d|gcd(\omega, j)}\varphi(d) S(ω,m)=∑j=1mφ(gcd(ω,j)ω)φ(j)∑d∣gcd(ω,j)φ(d)
- → \rightarrow → S ( ω , m ) = ∑ j = 1 m φ ( j ) ∑ d ∣ g c d ( ω , j ) φ ( d ) φ ( ω g c d ( ω , j ) ) S(\omega, m) =\sum_{j = 1} ^ m\varphi(j)\sum_{d|gcd(\omega, j)}\varphi(d)\varphi(\frac{\omega}{gcd(\omega, j)}) S(ω,m)=∑j=1mφ(j)∑d∣gcd(ω,j)φ(d)φ(gcd(ω,j)ω)
- → \rightarrow → S ( ω , m ) = ∑ j = 1 m φ ( j ) ∑ d ∣ g c d ( ω , j ) φ ( ω d ) S(\omega, m) =\sum_{j = 1} ^ m\varphi(j)\sum_{d|gcd(\omega, j)} \varphi(\frac{\omega}{d}) S(ω,m)=∑j=1mφ(j)∑d∣gcd(ω,j)φ(dω)
- → \rightarrow → S ( ω , m ) = ∑ d ∣ ω φ ( ω d ) ∑ j = 1 ⌊ m d ⌋ φ ( j ∗ d ) S(\omega, m) =\sum_{d|\omega}\varphi(\frac{\omega}{d})\sum_{j = 1}^{\lfloor \frac{m}{d} \rfloor}\varphi(j*d) S(ω,m)=∑d∣ωφ(dω)∑j=1⌊dm⌋φ(j∗d)
- → \rightarrow → S ( ω , m ) = ∑ d ∣ ω φ ( ω d ) S ( d , ⌊ m d ⌋ ) S(\omega, m) =\sum_{d|\omega}\varphi(\frac{\omega}{d})S(d,\lfloor \frac{m}{d}\rfloor) S(ω,m)=∑d∣ωφ(dω)S(d,⌊dm⌋)
- 当 ω = 1 \omega=1 ω=1时杜教筛求 ∑ i = 1 m φ ( i ) \sum_{i=1}^{m}\varphi(i) ∑i=1mφ(i)
- O ( 能 过 ) O(能过) O(能过)
代码:
/**************************************************************
Problem: 3512
User: Ransln
Language: C++
Result: Accepted
Time:6100 ms
Memory:27852 kb
****************************************************************/
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int Max = 1e6 + 100;
const int MOD = 1e9 + 7;
int prime[Max], tot, phi[Max], sum[Max];
bool vis[Max];
void init(){
phi[1] = 1;
for(int i = 2; i < Max; i++){
if(!vis[i])prime[tot ++] = i, phi[i] = i - 1;
for(int j = 0; j < tot; j++){
int tmp = i * prime[j];
if(tmp >= Max)break;
vis[tmp] = true;
if(i % prime[j] == 0){
phi[tmp] = phi[i] * prime[j];
break;
}
phi[tmp] = phi[i] * (prime[j] - 1);
}
}
for(int i = 1; i < Max; i++)sum[i] = (sum[i - 1] + phi[i]) % MOD;
}
vector<int> divide(ll x){
vector<int> now;
for(int i = 0; i < tot; i++){
if(prime[i] * prime[i] > x)break;
if(x % prime[i] == 0){
now.push_back(prime[i]);
while(x % prime[i] == 0)x /= prime[i];
}
}
if(x != 1)now.push_back((int)x);
return now;
}
map<ll, ll> Hash;
map<ll, ll> M;
ll solve(ll m){
if(m < Max)return sum[m];
if(Hash.count(m))return Hash[m];
ll ans = 0;
for(ll i = 2, j; i <= m; i = j + 1){
j = m / (m / i);
ans = (ans + (j - i + 1) * solve(m / i) % MOD) % MOD;
}
ans = (((((1 + m) * m) / 2) % MOD) - ans + MOD)% MOD;
return Hash[m] = ans;
}
ll S(ll n, ll m){
if(m == 1)return phi[n];
if(n == 1)return solve(m);
if(m == 0)return 0;
if(M.count(n * (ll)1e10 + m))return M[n * (ll)1e10 + m];
vector<int> p = divide(n);
int len = p.size();
ll ans = 0;
for(int i = 0; i < (1 << len); i++){
ll tmp = 1;
for(int j = 0; j < len; j++){
if(i >> j & 1)tmp = tmp * p[j];
}
ans = (ans + phi[n / tmp] * S(tmp, m / tmp)) % MOD;
}
return M[n * (ll)1e10 + m] = ans;
}
int main(){
ll n, m;init();
scanf("%lld%lld", &n, &m);
ll ans = 0;
for(int i = 1; i <= n; i++){
vector<int> p = divide(i);
int len = p.size(), x = 1;
for(int j = 0; j < len; j++) x = x * p[j];
ans = (ans + i / x * S(x, m)) % MOD;
}
printf("%lld\n", ans);
return 0;
}