P3327 [SDOI2015]约数个数和
Posted olinr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3327 [SDOI2015]约数个数和相关的知识,希望对你有一定的参考价值。
\(\color{#0066ff}{ 题目描述 }\)
设\(d(x)\)为\(x\)的约数个数,给定\(N、M\),求?\(\sum^N_{i=1}\sum^M_{j=1}d(ij)\)
\(\color{#0066ff}{输入格式}\)
输入文件包含多组测试数据。第一行,一个整数T,表示测试数据的组数。接下来的T行,每行两个整数N、M。
\(\color{#0066ff}{输出格式}\)
T行,每行一个整数,表示你所求的答案。
\(\color{#0066ff}{输入样例}\)
2
7 4
5 6
\(\color{#0066ff}{输出样例}\)
110
121
\(\color{#0066ff}{数据范围与提示}\)
1<=N, M<=50000
1<=T<=50000
\(\color{#0066ff}{ 题解 }\)
题目要求
\[ \sum_{i=1}^n\sum_{j=1}^md(ij) \]
看似不好求,然而有结论。。。
\[ \sum_{i=1}^n\sum_{j=1}^m\sum_{x|i}\sum_{y|j} [gcd(x, y)==1] \]
然后就是套路了
\[ \sum_{i=1}^n\sum_{j=1}^m\sum_{x|i}\sum_{y|j} \sum_{d|gcd(x, y)} \mu(d) \]
枚举x和y,注意还要是i和j的约数
\[ \sum_{d = 1}^{min(n,m)}\sum_{i=1}^n\sum_{j=1}^m\sum_{x=1}^{\lfloor\frac i d \rfloor}\sum_{y=1}^{\lfloor\frac j d \rfloor}[xd|i\&\&yd|j] \mu(d) \]
能提前的全部提前
\[ \sum_{d = 1}^{min(n,m)}\mu(d)\sum_{i=1}^n\sum_{j=1}^m\sum_{x=1}^{\lfloor\frac i d \rfloor}\sum_{y=1}^{\lfloor\frac j d \rfloor}[xd|i\&\&yd|j] \]
\[ \sum_{d = 1}^{min(n,m)}\mu(d)\sum_{i=1}^n\sum_{x=1}^{\lfloor\frac i d \rfloor}[xd|i]\sum_{j=1}^m\sum_{y=1}^{\lfloor\frac j d \rfloor}[yd|j] \]
最后就成这东西了
\[ \sum_{d = 1}^{min(n,m)}\mu(d)\sum_{x=1}^{\lfloor\frac n d \rfloor}\lfloor\frac{n}{xd}\rfloor\sum_{y=1}^{\lfloor\frac m d \rfloor}\lfloor\frac{m}{yd}\rfloor \]
把\(\lfloor\frac{n}{d}\rfloor\)当成一个整体,那么其实就是\(\begin{aligned}\sum_{x=1}^n \lfloor\frac{n}{x}\rfloor\end{aligned}\)
直接数列分块即可
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 5e4 + 100;
LL pri[maxn], mu[maxn], cnt[maxn], ans[maxn], tot;
bool vis[maxn];
void predoit() {
mu[1] = 1;
for(int i = 2; i < maxn; i++) {
if(!vis[i]) pri[++tot] = i, mu[i] = -1;
for(int j = 1; j <= tot && (LL)i * pri[j] < maxn; j++) {
vis[i * pri[j]] = true;
if(i % pri[j] == 0) break;
else mu[i * pri[j]] = -mu[i];
}
}
for(int i = 1; i < maxn; i++) {
mu[i] += mu[i - 1];
for(LL l = 1, r; l <= i; l = r + 1) {
r = i / (i / l);
ans[i] += (r - l + 1) * (i / l);
}
}
}
LL work(LL n, LL m) {
LL res = 0;
for(LL l = 1, r; l <= std::min(n, m); l = r + 1) {
r = std::min(n / (n / l), m / (m / l));
res += (mu[r] - mu[l - 1]) * ans[n / l] * ans[m / l];
}
return res;
}
int main() {
predoit();
for(int T = in(); T --> 0;) printf("%lld\n", work(in(), in()));
return 0;
}
以上是关于P3327 [SDOI2015]约数个数和的主要内容,如果未能解决你的问题,请参考以下文章
洛谷P3327 [SDOI2015]约数个数和 莫比乌斯反演