[luogu]P2522 [HAOI2011]Problem b[莫比烏斯反演]
阿新 • • 發佈:2018-12-11
題目
組詢問,每組詢問A,B,C,D,K共5個引數計算
資料範圍:所有
題解
設分別為為倍數和等於的個數,有
由莫比烏斯反演知:
問題即求,由於上界下界的問題,利用容斥分別計算即可:
以上界進行表示
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; using LL = long long; const int MAXN = 5e4 + 5; int T, A, B, C, D, K; bool noprime[MAXN]; int prime[MAXN], cnt_p, mu[MAXN]; void Euler_sieve(int top); int pre[MAXN]; LL solve(int, int); int main(){ ios::sync_with_stdio(false); Euler_sieve(5e4); cin >> T; while(T--){ cin >> A >> B >> C >> D >> K; LL ans = 0; ans += solve(B / K, D / K); ans -= solve(B / K, (C - 1) / K) + solve((A - 1) / K, D / K); ans += solve((A - 1) / K, (C - 1) / K); cout << ans << endl; } return 0; } LL solve(int n, int m){ int l, r, top = min(n, m); LL res = 0; for(l = 1; l <= top; l = r + 1){ r = min(n / (n / l), m / (m / l)); res += 1LL * (pre[r] - pre[l - 1]) * (n / l) * (m / l); } return res; } void Euler_sieve(int top){ int i, j; mu[1] = 1; for(i = 2; i <= top; i++){ if(!noprime[i]) prime[++cnt_p] = i, mu[i] = -1; for(j = 1; j <= cnt_p && prime[j] * i <= top; j++){ noprime[prime[j] * i] = true; if(i % prime[j] == 0) break; mu[prime[j] * i] = -mu[i]; } } for(i = 1; i <= top; i++) pre[i] = pre[i - 1] + mu[i]; }