题目链接:
HDU 1695 GCD
题意:
求
x∈[a,b],y∈[c,d],且gcd(x,y)=k的(x,y)的无序对对数。a=c=1
分析:
这道题之前有莫比乌斯反演做过,现在纯粹用容斥以及求
[1,r]
中和
x
互质数个数也能做。
因为这是无序的,我们不妨设
用
extra
记录当
i∈[1,d]
时
[1,d]
中和
i
互质的数字个数,那么其实这部分是多算了的,而且除了
用
ans
记录当
i∈(d,b]
时
[1,d]
中和
i
互质的数字个数,这部分是没有多算了的。
所以最终的答案就是:
只不过这样做要比用莫比乌斯做耗时多点,而且也需要预处理 105 以内每个数的质因数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <ctime>
#include <cassert>
#include <vector>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
const int MAX_N = 100010;
int vis[MAX_N];
vector <int> fac[MAX_N];
void GetFactor()
{
memset(vis, 0, sizeof(vis));
for(int i = 2; i < MAX_N; ++i) {
if(vis[i] == 0) {
fac[i].push_back(i);
for(int j = i * 2; j < MAX_N; j += i) {
fac[j].push_back(i);
vis[j] = 1;
}
}
}
}
inline int work(int r, int x) //[1, r]中和x互素的数个数
{
if(x == 1) return r;
int res = 0, size = fac[x].size();
for(int i = 1; i < (1 << size); ++i) {
int bits = 0, mul = 1;
for(int j = 0; j < size; ++j) {
if(i & (1 << j)) {
bits++;
mul *= fac[x][j];
}
}
if(bits & 1) res += r / mul;
else res -= r / mul;
}
return r - res;
}
int main()
{
GetFactor();
int T, cases = 0, a, b, c, d, k;
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;
if(b < d) swap(b, d);
ll ans = 0, extra = 0, tmp;
for(int i = 1; i <= b; ++i) {
//printf("d = %d i = %d work(d, i) = %d\n", d, i, work(d, i));
tmp = work(d, i);
if(i <= d) extra += tmp;
else ans += tmp;
}
//printf("extra = %lld\n", extra);
printf("Case %d: %lld\n", ++cases, ans + (extra + 1)/ 2);
}
return 0;
}