[NOI2010]能量採集[容斥,莫比烏斯反演]
阿新 • • 發佈:2018-12-11
題意
計算,表示在範圍內的個數
資料範圍:
題解
這裡介紹容斥和莫比烏斯反演兩種方法(如果想系統瞭解這種題目的各種大體思路可以看兩兩gcd求和的4種方法) 下面先設分別為為倍數和等於的個數,有
容斥(篩法)
容斥是利用先計算到每個,再通過從後向前處理得到每個最後針對問題選取需要的求解
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]; }
莫比烏斯反演
由莫比烏斯反演知:
問題的
這裡如果是單次詢問可以不進一步化解直接求和,時間複雜度為
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]); }
若進一步化解
這種化解一般都額外需要一個的字首和(不化解為),而每次計算只需要,一般針對多次詢問
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]); }