求$(i,j)=k$的一系列模板题之一。
但是这里i,j是有下界的,注意用容斥去掉重复组,其他都一样了。
/** @Date : 2017-09-09 19:21:18 * @FileName: bzoj 2301 莫比乌斯反演 多组 范围内 GCD=k.cpp * @Platform: Windows * @Author : Lweleth (SoungEarlf@gmail.com) * @Link : https://github.com/ * @Version : $Id$ */ #include <bits/stdc++.h> #define LL long long #define PII pair<int ,int> #define MP(x, y) make_pair((x),(y)) #define fi first #define se second #define PB(x) push_back((x)) #define MMG(x) memset((x), -1,sizeof(x)) #define MMF(x) memset((x),0,sizeof(x)) #define MMI(x) memset((x), INF, sizeof(x)) using namespace std; const int INF = 0x3f3f3f3f; const int N = 5e4+20; const double eps = 1e-8; int pri[N]; int mu[N]; int c = 0; int vis[N]; LL sum[N]; void prime() { MMF(vis); mu[1] = 1; for(int i = 2; i < N; i++) { if(!vis[i]) pri[c++] = i, mu[i] = -1; for(int j = 0; j < c && i * pri[j] < N; j++) { vis[i * pri[j]] = 1; if(i % pri[j] == 0) { mu[i * pri[j]] = 0; break; } else mu[i * pri[j]] = -mu[i]; } } sum[0] = 0; for(int i = 1; i < N; i++) sum[i] += sum[i - 1] + mu[i]; } LL getsum(LL n, LL m) { LL ans = 0; if(n > m) swap(n, m); for(int i = 1, last; i <= n; i = last + 1) { last = min(n/(n/i), m/(m/i)); ans += (LL)(n / i) * (m / i) * (sum[last] - sum[i - 1]); } return ans; } int main() { int T; prime(); cin >> T; while(T--) { LL a, b, c, d, k; scanf("%lld%lld%lld%lld%lld", &a, &b, &c, &d, &k); a = (a - 1) / k; b = b / k; c = (c - 1) / k; d = d / k; LL ans = getsum(a, c) + getsum(b, d) - getsum(a, d) - getsum(b, c);//容斥 printf("%lld ", ans); } return 0; }