码迷,mamicode.com
首页 > 其他好文 > 详细

[51nod1227]平均最小公倍数(莫比乌斯反演+杜教筛)

时间:2019-10-19 00:04:53      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:net   namespace   前缀   isp   ali   一个   最小   begin   sdn   

题意

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

分析

只需要求出前缀和,

$$\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}$$

其后面部分提出来,即求 $\sum_{i=1}^n i\cdot [gcd(i,n)=1]$,对于这种一个值固定的gcd求和有一个套路,即倒序两两配对:

若 $n=1$,和为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)$,所以和为 $ n\varphi (n) /2$.

综合得 $\displaystyle \sum_{i=1}^n i\cdot [gcd(i,n)=1] = \frac{n\varphi (n)+[n=1]}{2}$.

具体实现上,$[i=1]$ 只成立 $n$,除2可以提出来,即 原式 = $\displaystyle \frac{1}{2}(\sum_{d=1}^n \sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor} i\varphi (i) + n)$.

现在唯一得问题是如何求 $\displaystyle  S(n) = \sum_{i=1}^n i\varphi (i)$.

根据杜教筛,

设 $\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)$.

再最外层套个数论分块即可。

代码

#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<ll, ll> mp_phi_d;  //可换成unordered_map,约快3倍
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;  //%敲成*,浪费一个小时
  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) % 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;
}

 

 

参考链接:

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

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

 

[51nod1227]平均最小公倍数(莫比乌斯反演+杜教筛)

标签:net   namespace   前缀   isp   ali   一个   最小   begin   sdn   

原文地址:https://www.cnblogs.com/lfri/p/11701388.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!