HDU 1695 容斥
又是求gcd=k的题,稍微有点不同的是,(i,j)有偏序关系,直接分块好像会出现问题,还好数据规模很小,直接暴力求就行了。
/** @Date : 2017-09-15 18:21:35 * @FileName: HDU 1695 容斥 或 莫比乌斯反演.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 = 1e5+20; const double eps = 1e-8; LL pri[N]; LL mu[N]; LL sum[N]; int c = 0; bool vis[N]; void prime() { MMF(vis); MMF(sum); 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 get_sum(LL n, LL m) { if(n > m) swap(n, m); int mi = min(n, m); LL ans = 0; for(int i = 1, last; i <= mi; i++, last = last + 1) { last = min(n/(n/i), m/(m/i));//由于有重复情况 不能直接分块? ans += (LL)(n / i) * (m / i) * (sum[i] - sum[i - 1]); } return ans; } int main() { int T; prime(); cin >> T; int cnt = 0; while(T--) { LL a, b, c, d, k; scanf("%lld%lld%lld%lld%lld", &a, &b, &c, &d, &k); if(k == 0) { printf("Case %d: 0\n", ++cnt); continue; } a = (a - 1) / k; b = b / k; c = (c - 1) / k; d = d / k; LL ans = get_sum(a, c) + get_sum(b, d) - get_sum(a, d) - get_sum(b, c) - get_sum(min(b,d), min(b,d)) / 2; printf("Case %d: %lld\n", ++cnt, ans); /*LL ans = 0; LL t = 0; for(int i = 1; i <= b; i++) ans += (b / i) * (d / i) * mu[i]; for(int i = 1; i <= d; i++) t += (min(b,d)/ i) * (min(b, d) / i) * mu[i]; printf("Case %d: %lld\n", ++cnt, ans - t / 2);*/ } return 0; }