luogu

链接:https://www.luogu.org/problemnew/show/P3455
思路:求$sum_{i = 1} ^ asum_{j = 1} ^ b[gcd(i, j) = d]$。我们设:

那么有:

从而有:

$将枚举项 lfloorfrac{k}{d}rfloor 变为t$:

然后有多组数据,用一下整除分块求前缀和就可以解决了。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

using namespace std;

const int maxn = 5e4 + 233;
typedef long long ll;
ll sum[maxn];
bool vis[maxn];
int mu[maxn];
vector<int> prime;
int T, a, b, d;

void (){
mu[1] = 1;
for(int i = 2; i < maxn; i++){
if(!vis[i]){
mu[i] = -1;
prime.emplace_back(i);
}
for(int j = 0; j < prime.size() && i * prime[j] < maxn; j++){
vis[i * prime[j]] = 1;
if(i % prime[j] == 0) break;
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1; i < maxn; i++) sum[i] = sum[i - 1] + mu[i];
}

int main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
init();
cin >> T;
while(T--){
cin >> a >> b >> d;
a /= d, b /= d;
if(a > b) swap(a, b);
ll res = 0;
for(int l = 1, r; l <= a; l = r + 1){
r = min(a / (a / l), b / (b / l));
res += 1ll * (a / l) * (b / l) * (sum[r] - sum[l - 1]);
}
cout << res << 'n';
}
return 0;
}