1. 程式人生 > >[NOI2010]能量採集[容斥,莫比烏斯反演]

[NOI2010]能量採集[容斥,莫比烏斯反演]

題意

計算\sum (2*i-1)f[i],f[i]表示在1 \leq x \leq N, 1\leq y \leq M範圍內gcd(x,y)=i的個數

資料範圍:N,M\leq 10^5

題解

這裡介紹容斥和莫比烏斯反演兩種方法(如果想系統瞭解這種題目的各種大體思路可以看兩兩gcd求和的4種方法) 下面先設F[x],f[x]分別為gcd(i,j)(1 \leq i \leq N,1 \leq j \leq M)x​​​​​​倍數和等於x的個數,有F[n]=\sum_{n|d}f[d]=\lfloor \frac{N}{n} \rfloor\lfloor \frac{M}{n} \rfloor

容斥(dp篩法)

容斥是利用F[n]=\sum_{n|d}f[d]=\lfloor \frac{N}{n} \rfloor\lfloor \frac{M}{n} \rfloor先計算到每個F[i],再通過從後向前處理得到每個f[i]最後針對問題選取需要的求解

  for(i = 1; i <= top; i++) F[i] = (LL)(N / i) * (M / i);
  for(i = top; i >= 1; i--){
    f[i] = F[i];
    for(j = i * 2; j <= top; j += i)
      f[i] -= f[j];
  }

莫比烏斯反演

由莫比烏斯反演知:f[n]=\sum_{n|d}\mu (\frac{d}{n})F[d]

問題的ans=\sum (2*i-1) \sum_{i|d}\mu (\frac{d}{i})[\frac{N}{d}][\frac{M}{d}] =\sum (2*i-1) \sum_{j=1}^{min([\frac{N}{i}],[\frac{M}{i}])}\mu (j)[\frac{N}{ij}][\frac{M}{ij}]

這裡如果是單次詢問可以不進一步化解直接求和,時間複雜度為O(N)

  for(i = 1; i <= top; i++) pre[i] = pre[i - 1] + mu[i];
  for(i = 1; i <= top; i++) sum[i] = sum[i - 1] + (2 * i - 1);
  int l, r; LL ans = 0;
  for(l = 1; l <= top; l = r + 1){
    r = min(N / (N / l), M / (M / l));
    ans += (LL)solve(N / l, M / l) * (sum[r] - sum[l - 1]);
  }

若進一步化解

\\ ans=\sum_{i=1}^{min(N,M)}\sum_{j=1}^{min([\frac{N}{i}],[\frac{M}{i}])} (2i-1)\mu (j) [\frac{N}{ij}][\frac{M}{ij}]\\ =\sum_{k=1}^{min(N,M)} [\frac{N}{k}][\frac{M}{k}] \sum_{i|k} (2i-1)\mu (\frac{k}{i})

這種化解一般都額外需要一個O(NlogN)的字首和(不化解為O(N)),而每次計算只需要O(\sqrt N),一般針對多次詢問

  for(i = 1; i <= top; i++)
    for(j = i; j <= top; j += i)
      sum[j] += mu[j / i] * (2 * i - 1);
  for(i = 1; i <= top; i++) sum[i] += sum[i - 1];
  int l, r; LL ans = 0;
  for(l = 1; l <= top; l = r + 1){
    r = min(N / (N / l), M / (M / l));
    ans += (LL)(N / l) * (M / l) * (sum[r] - sum[l - 1]);
  }