hdu1695 莫比乌斯反演
Sample Input
2 1 3 1 5 1 1 11014 1 14409 9
Sample Output
Case 1: 9 Case 2: 736427
Hint
For the first sample input, all the 9 pairs of numbers are (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 5), (3, 4), (3, 5).
题意:给你 a,b,c,d,e,求 a ≤ x ≤ b,c ≤ y ≤ d时,gcd(x,y) = e的情况
思路:
偶然看到一道题用的是莫比乌斯反演,发现不会就去学习了一下。
本题gcd(x,y) = e 可以看成 gcd(x/e,y/e) = 1,然后利用莫比乌斯反演求出
/* 直接用莫比乌斯反演,由于 (3.5)(5.3)看做相同的, 在最后减去他们即可 */ #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <vector> #include <algorithm> typedef long long ll; using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 1e6+10; int is_prime[maxn]; int prime[maxn]; int mu[maxn]; int tot; void Moblus() { tot = 0; memset(is_prime,0,sizeof(is_prime)); mu[1] = 1; for(int i = 2; i <= maxn; i++) { if(!is_prime[i]) { prime[tot++] = i; mu[i] = -1; } for(int j = 0; j < tot; j++) { if(prime[j]*i>maxn) break; is_prime[i*prime[j]] = 1; if(i % prime[j]) //prime[j]不重复 { mu[i*prime[j]] = -mu[i]; } else { mu[i*prime[j]] = 0; break; } } } } int main() { int T; int a,b,c,d,k; Moblus(); int cas = 1; scanf("%d",&T); while(T--) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); printf("Case %d: ",cas++); if(k == 0) { printf("0\n"); continue; } b /= k; d /= k; if(b > d) swap(b,d); ll ans = 0; for(int i = 1; i <= b; i++) { ans += (ll)mu[i]*(b/i)*(d/i); // printf("%d %d %d\n",mu[i],b/i,d/i); } ll ans1 =0; for(int i = 1; i <= b; i++) //计算重复部分 ans1 += (ll)mu[i]*(b/i)*(b/i); printf("%I64d\n",ans-ans1/2); } return 0; }