[51nod1227] Average least common multiple (Mobius inversion + Du teach sieve)

The meaning of problems

求 $\sum_{i=a}^b \sum_{j=1}^i \frac{lcm(i,j)}{i}$.

analysis

Just requires a prefix and,

$$\begin{aligned}
\sum_{i=1}^n \sum_{j=1}^i \frac{lcm(i,j)}{i} &= \sum_{i=1}^n \sum_{j=1}^i \frac{j}{gcd(i,j)} \\
&= \sum_{d=1}^n \sum _{i=1}^n \sum_{j=1}^i \frac{j}{d} \cdot [gcd(i,j)=1] \\
&=  \sum_{d=1}^n \sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor} \sum_{j=1}^i j \cdot [gcd(i,j)=1]
\end{aligned}$$

Its rear part raised, i.e. seek $ \ sum_ {i = 1} ^ ni \ cdot [gcd (i, n) = 1] $, for which a fixed value has a gcd summation routine, i.e. reverse twenty-two pair:

If $ n = 1 $, and is 1;

若 $n>1$,因为 $gcd(i, n) = gcd(n-i, n)$ 且 $\displaystyle  \sum_{i=1}^n i\cdot [gcd(i,n)=1] = \sum_{i=1}^{n-1} i\cdot [gcd(i,n)=1]$,

$ \ Displaystyle \ sum_ {i = 1} ^ {n-1} i \ cdot [gcd (i, n) = 1] + \ sum_ {i = n-1} ^ 1i \ cdot [gcd (i, n) = 1] = n \ varphi (n) $, and so for the $ n \ varphi (n) / 2 $.

Integrated obtained $ \ displaystyle \ sum_ {i = 1} ^ ni \ cdot [gcd (i, n) = 1] = \ frac {n \ varphi (n) + [n = 1]} {2} $.

The specific implementation, $ [i = 1] $ established only $ n-$, except 2 can be raised, i.e., the original formula = $ \ displaystyle \ frac {1} {2} (\ sum_ {d = 1} ^ n \ sum_ {i = 1} ^ {\ left \ lfloor \ frac {n} {d} \ right \ rfloor} i \ varphi (i) + n) $.

The only problem is how to get request $ \ displaystyle S (n) = \ sum_ {i = 1} ^ ni \ varphi (i) $.

According to Du teach sieve,

设 $\displaystyle S(n) = \sum_{i=1}^n f(i)$,$f(n) = n\varphi (n), \ g(n) = n$.

$\displaystyle f*g = \sum_{d|n} d \varphi (d) \cdot \frac{n}{d} = n\sum_{d|n}\varphi (d) = n^2$.

因此 $\displaystyle S(n) = \sum_{i=1}^n i^2 - \sum_{d=2}^n d\cdot S(\left \lfloor \frac{n}{d} \right \rfloor)$.

On the outermost layer and then the number of sets to block.

Code

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <map>
#include<unordered_map>
using namespace std;
const int maxn = 2000010;
typedef long long ll;
const ll mod = 1000000007;
const ll inv2 = (mod+1)>>1;
const ll inv6 = 166666668;  //166666668
ll T, a, b, pri[maxn], tot, phi[maxn], sum_phi_d[maxn];
bool vis[maxn];
unordered_map MOD;<LL, LL> mp_phi_d;   // can be replaced unordered_map, about three times faster 
LL S_phi_d (LL X) {
   IF (X <MAXN) return sum_phi_d [X];
   IF (mp_phi_d [X]) return mp_phi_d [X]; 
  LL RET = X * (X + . 1 )% MOD * ( 2 * X% MOD + . 1 )% MOD * INV6% MOD;   // % knock into *, wasting one hour 
  for (LL I = 2 , J; I <= X ; I = J + . 1 ) { 
    J = X / (X / I); 
    RET = (RET - S_phi_d (X / I) * (I + J)% MOD * (J-I + . 1 )% MOD * INV2% MOD MOD +)% 
  } 
  return mp_phi_d[x] = ret;
}
void initPhi_d()
{
  phi[1] = 1;
  for (int i = 2; i < maxn; i++) {
    if (!vis[i]) pri[++tot] = i, phi[i] = i-1;
    for (int j = 1; j <= tot && i * pri[j] < maxn; j++) {
      vis[i * pri[j]] = true;
      if (i % pri[j] == 0)
      {
          phi[i * pri[j]] = phi[i] * pri[j] % mod;
          break;
      }
      else
      {
          phi[i * pri[j]] = phi[i] * phi[pri[j]] % mod;
      }
    }
  }
  for (int i = 1; i < maxn; i++) sum_phi_d[i] = (sum_phi_d[i - 1] + phi[i]*i) % mod;
}

//ll G(ll n)
//{
//    //printf("G:%lld\n", n);
//    return (S_phi_d(n)+1) % mod;
//}
ll solve(ll n)
{
    ll res = 0;
    for(ll i = 1, j;i <= n;i = j+1)
    {
        j = n / (n / i);
        res = (res + S_phi_d(n/i) * (j-i+1) % mod) % mod;
    }
    return (res+n)*inv2%mod;
}


int main() {
  initPhi_d();
  scanf("%lld%lld", &a, &b);
  printf("%lld\n", (solve(b)-solve(a-1)+mod) % mod);
  return 0;
}

 

 

Reference links:

1. https://blog.csdn.net/FromATP/article/details/74999989

2. https://www.cnblogs.com/owenyu/p/7397687.html

 

Guess you like

Origin www.cnblogs.com/lfri/p/11701388.html