题目链接:
HDU 1695 GCD
题意:
求
x∈[a,b],y∈[c,d],且gcd(x,y)=k的(x,y)的无序对对数。a=c=1
分析:
和BZOJ 2301的区别就是这里是无序对。
不妨设b≤d,,利用容斥原理那么多计算的部分就是x∈[1,b],y∈[1,b]的部分,那么减掉这部分就好了。
还要注意每次计算都是计算有序的!
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <string>
#include <bitset>
using namespace std;
typedef long long ll;
const int MAX_N = 100010;
int T, cases = 0, a, b, c, d, k, prime_cnt;
int mu[MAX_N], vis[MAX_N], prime[MAX_N];
void init()
{
prime_cnt = 0;
mu[1] = 1;
memset(vis, 0, sizeof(vis));
for(int i = 2; i < MAX_N; i++) {
if(vis[i] == 0) {
prime[prime_cnt++] = i;
mu[i] = -1;
}
for(int j = 0; j < prime_cnt && i * prime[j] < MAX_N; j++) {
vis[i * prime[j]] = 1;
if(i % prime[j] ) {
mu[i * prime[j]] = -mu[i];
}else {
mu[i * prime[j]] = 0;
break;
}
}
}
}
ll solve(int n, int m)
{
ll res = 0;
int low = min(n, m);
for(int i = 1; i <= low; ++i) {
res += (ll)mu[i] * (n / i) * (m / i);
}
ll tmp = 0;
for(int i = 1; i <= low; ++i) {
tmp += (ll)mu[i] * (low / i) * (low / i);
}
res -= tmp / 2;
return res;
}
int main()
{
init();
scanf("%d", &T);
while(T--) {
scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
if(k == 0) {
printf("Case %d: 0\n", ++cases);
continue;
}
b /= k, d /= k;
printf("Case %d: %lld\n", ++cases, solve(b, d));
}
return 0;
}