题目链接
思路:
论文题,首先可以筛选出
[1,a],[1,b]
[
1
,
a
]
,
[
1
,
b
]
以内
gcd
g
c
d
是
d
d
的倍数的个数,设
F(i):在[1,x],[1,y]
F
(
i
)
:
在
[
1
,
x
]
,
[
1
,
y
]
中
gcd=i
g
c
d
=
i
的倍数的个数,那么根据容斥原理,
ans=F(1)−F(2)−F(3)−F(5)+F(6)−F(7)...
a
n
s
=
F
(
1
)
−
F
(
2
)
−
F
(
3
)
−
F
(
5
)
+
F
(
6
)
−
F
(
7
)
.
.
.
,
F(i)
F
(
i
)
的正负或者是
0
0
是的莫比乌斯函数,知道
xd,yd
x
d
,
y
d
在很大一部分区间是相同的,大约是
n−−√
n
级别,所以预处理莫比乌斯函数前缀和,再枚举
xd,yd
x
d
,
y
d
的值,时间
nn−−√
n
n
。
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 5e4 + 10;
using namespace std;
int n, m, T, kase = 1;
int p[maxn], num[maxn], cnt;
int sum[maxn], vis[maxn];
void init() {
p[1] = 1;
for(int i = 2; i < maxn; i++) {
if(!num[i]) {
for(int j = i; j < maxn; j += i) if(!num[j]) num[j] = i;
}
int x = i, tot = 0;
vector<int> vec;
while(x > 1) {
int px = num[x];
vec.push_back(px);
if(vis[px]) { tot = -1; break; }
vis[px]++; x /= px; tot++;
}
for(int i = 0; i < vec.size(); i++) vis[vec[i]] = 0;
if(tot == -1) p[i] = 0;
else if(tot & 1) p[i] = -1;
else p[i] = 1;
}
sum[0] = 0;
for(int i = 1; i < maxn; i++) sum[i] = sum[i - 1] + p[i];
}
ll solve(int x, int y, int d) {
int t1 = x / d, t2 = y / d;
int min_t = min(t1, t2);
ll ans = 0;
for(int x = 1; x <= min_t; x++) {
int ax = t1 / x, bx = t2 / x;
ll fx = (ll)ax * bx;
int next_x;
int tx1 = t1 / ax, tx2 = t2 / bx;
next_x = min(tx1, tx2);
ans += fx * (sum[next_x] - sum[x - 1]);
x = next_x;
}
return ans;
}
const int MAX = 10000;
char buf[MAX], *ps = buf, *pe = buf + 1;
inline void rnext() {
if(++ps == pe) pe = (ps = buf) + fread(buf, sizeof(char), sizeof(buf) / sizeof(char), stdin);
}
template <class T>
inline bool in(T &ans) {
ans = 0;
T f = 1;
if(ps == pe) return false;//EOF
do{
rnext();
if('-' == *ps) f = -1;
} while(!isdigit(*ps) && ps != pe);
if(ps == pe) return false;//EOF
do {
ans = (ans<<1)+(ans<<3)+*ps-48;
rnext();
} while(isdigit(*ps) && ps != pe);
ans *= f;
return true;
}
char bufout[MAX], outtmp[50],*pout = bufout, *pend = bufout + MAX;
inline void write() {
fwrite(bufout, sizeof(char), pout - bufout, stdout);
pout = bufout;
}
inline void out_char(char c) { *(pout++) = c; if(pout == pend) write(); }
inline void out_str(char *s) {
while(*s) {
*(pout++) = *(s++);
if(pout == pend) write();
}
}
template <class T>
inline void out_int(T x) {
if(!x) {
out_char('0');
return;
}
if(x < 0) x = -x,out_char('-');
int len = 0;
while(x) {
outtmp[len++] = x%10+48;
x /= 10;
}
outtmp[len] = 0;
for(int i = 0, j = len - 1; i < j; i++,j--) swap(outtmp[i],outtmp[j]);
out_str(outtmp);
}
int main() {
init(); in(n);
while(n--) {
int a, b, d;
in(a); in(b); in(d);
ll ans = solve(a, b, d);
out_int(ans); out_char('\n');
}
write();
return 0;
}