题意

给定a, b, c, d, k,求出:

\[\sum_{i=a}^b\sum_{j=c}^d[gcd(i, j) = k]
\]

题解

为方便表述,我们设

\[calc(\alpha, \beta) = \sum_{i=1}^{\alpha}\sum_{j=1}^{\beta}[gcd(i, j) = k]
\]

令\(A = \{ (x, y) | x < a\}\), \(B = \{(x, y)|y < c\}\),

根据容斥原理,

\[|S| = |U| - |A| - |B| + |A \cap B|
\]

所以,原式就是:

\[calc(b, d) - calc(a-1 ,d) - calc(b, c-1) + calc(a-1, c-1)
\]

这样我们就把一个询问拆分成了四个询问,即,问题就转换成了计算\(calc(\alpha, \beta)\)

\[f(x) = \sum_{i=1}^b\sum_{j=1}^d[gcd(i, j) = x]
\]

显然,f(x)并不方便计算,但是如果我们设

\[F(x) = \sum_{i=1}^b\sum_{j=1}^d[gcd(i, j) = \lambda, x|\lambda]
\]

我们可以得出F(x)与f(x)的关系,

\[F(x) = \sum_{x|d} f(d)
\]

F(x)就相对好计算的多,我们很容易有:

\[F(x) =\lfloor \frac{b}{i}\rfloor \lfloor\frac{d}{i} \rfloor
\]

但是这一点对于我这种蒟蒻来说并不显然,所以这里给出一个证明。

同样地,令\(\lambda = gcd(i, j)\),如果\(x|\lambda\),那么我们可以得出:

1.\(x|i\)

2.\(x|j\)

反过来证明必要性:

如果\(x|i \&\& x|j\),那么x一定是i和j的公约数,所以一定有

\(x \leq \lambda\)

又因为x和\(\lambda\)都是公约数,所以\(x|\lambda\),所以必要性得证。

所以x是i和j的公约数是数对(i, j)可以对F(x)的充分必要条件。

我们使用分步原理,首先在[1,n]中寻找x的倍数个数,然后在[1,m]里找,乘起来就可以了。

然后,根据mobius反演(《具体数学》P113 4.9 \(\phi\)函数与\(\mu\)函数)

\[f(x) =\sum_{d|x} \mu(d) F(\frac{x}{d})
\]

但是这种反演形式并不适合解此题,我们采取另外一种形式:

\[f(x) = \sum_{x|d} \mu(\frac{d}{x}) F(d) = \sum_{x|d}\mu(\frac{d}{x}) \lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor
\]

由于枚举倍数显然只需要枚举到min(n, m),所以复杂度为\(\Theta(n+m)\)

根据神犇的课件

观察式子,我们发现:

\(\lfloor \frac{n}{d} \rfloor\)的取值最多有\(2 \sqrt n\)种(约数的个数),所以如果我们枚举\(\lfloor \frac{n/m}{d} \rfloor\)的取值,只需要枚举\(2(\sqrt n + \sqrt m)\)即可,复杂度就成了\(\Theta (\sqrt n + \sqrt m)\)

对于同一个取值,\(\mu\)函数是不同的,但是属于一个区间,我们可以统一求和,维护一个前缀和即可。

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 50005;
int T, a, b, c, d, k;
int mu[maxn+5], sumu[maxn+5], prime[maxn+5], check[maxn+5];
int tot = 0;
void get_mu() {
memset(check, 0, sizeof(check));
mu[1] = 1;
for(int i = 2; i <= maxn; i++) {
if(!check[i]) {
prime[tot++] = i;
mu[i] = -1;
}
for(int j = 0; j < tot; j++) {
if(i * prime[j] > maxn) break;
check[i * prime[j]] = 1;
if(i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
} else {
mu[i * prime[j]] = -mu[i];
}
}
}
} void init() {
get_mu();
for(int i = 1; i <= maxn; i++) sumu[i] = sumu[i-1] + mu[i];
} int calc(int n, int m) {
n/=k;
m/=k;
int ret = 0;
int last;
if(n > m) swap(n, m);
for(int i = 1; i <= n; i = last + 1) {
last = min(n / (n/i), m / (m/i));
ret += (n / i) * (m / i) * (sumu[last] - sumu[i-1]);
}
return ret;
}
int main() {
init();
scanf("%d", &T);
while(T--) {
scanf("%d %d %d %d %d", &a, &b, &c, &d, &k);
int ans = calc(b, d) - calc(a-1, d) - calc(b, c-1) + calc(a-1, c-1);
printf("%d\n", ans);
}
return 0;
}

觉得自己好蠢。。。

[bzoj2301][HAOI2011]Problem B —— 莫比乌斯反演+容斥原理的更多相关文章

  1. BZOJ2301: [HAOI2011]Problem b[莫比乌斯反演 容斥原理]【学习笔记】

    2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 4032  Solved: 1817[Submit] ...

  2. BZOJ2301: [HAOI2011]Problem b 莫比乌斯反演

    分析:对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. 然后对于求这样单个的gcd(x,y)=k的, ...

  3. BZOJ2301:[HAOI2011]Problem b(莫比乌斯反演,容斥)

    Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input 第一行一个整数 ...

  4. [HAOI2011][bzoj2301] Problem b [莫比乌斯反演+容斥原理+分块前缀和优化]

    题面: 传送门 有洛谷就尽量放洛谷链接呗,界面友好一点 思路: 和HDU1695比较像,但是这一回有50000组数据,直接莫比乌斯反演慢慢加的话会T 先解决一个前置问题:怎么处理a,c不是1的情况? ...

  5. [BZOJ1101&BZOJ2301][POI2007]Zap [HAOI2011]Problem b|莫比乌斯反演

    对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a,y<=b,并且gcd(x,y)=d. 我们可以令F[n]=使得n|(x,y)的数对(x,y)个数 这个很容易得到,只需要让x, ...

  6. P2522 [HAOI2011]Problem b (莫比乌斯反演)

    题目 P2522 [HAOI2011]Problem b 解析: 具体推导过程同P3455 [POI2007]ZAP-Queries 不同的是,这个题求的是\(\sum_{i=a}^b\sum_{j= ...

  7. Bzoj 2301: [HAOI2011]Problem b(莫比乌斯反演+除法分块)

    2301: [HAOI2011]Problem b Time Limit: 50 Sec Memory Limit: 256 MB Description 对于给出的n个询问,每次求有多少个数对(x, ...

  8. BZOJ 2301: [HAOI2011]Problem b 莫比乌斯反演

    2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 1007  Solved: 415[Submit][ ...

  9. BZOJ.2301.[HAOI2011]Problem B(莫比乌斯反演 容斥)

    [Update] 我好像现在都看不懂我当时在写什么了=-= \(Description\) 求\(\sum_{i=a}^b\sum_{j=c}^d[(i,j)=k]\) \(Solution\) 首先 ...

随机推荐

  1. Python学习第一弹

    开发语言: 高级:Python.java.PHP  C#   GO  ruby   C++           ——>字节码   低级:C.汇编                          ...

  2. manjaro安装teamviewer后无法打开

    点桌面快捷方式一闪而过 命令行运行提示 $ teamviewer /opt/teamviewer/tv_bin/script/tvw_exec:行7: /opt/teamviewer/logfiles ...

  3. maven打包成jar

    maven pom.xml中添加依赖 <build> <plugins> <plugin> <groupId>org.apache.maven.plug ...

  4. WPF里ItemsControl的分组实现

    我们在用到ItemsControl时,有时会用到分组,如ListBox,ListView,DataGrid.WPF的ItemsControl可以实现分组,是依托于GroupStyle,以ListBox ...

  5. luoguP1726 上白泽慧音

    P1726 上白泽慧音 题目描述 在幻想乡,上白泽慧音是以知识渊博闻名的老师.春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄.因此慧音决定换一个能够聚集最多人数的村 ...

  6. 《Cracking the Coding Interview》——第14章:Java——题目5

    2014-04-26 19:06 题目:Java中的对象反射机制是什么?有鼠么用? 解法:完全不了解,因为java编程经验太少,完全没用过.查了一些资料后,感觉反射机制是个强大并需要边用边体会的强大工 ...

  7. python学习笔记一:数据类型

    一.Python文件类型 1.源代码 hello.py: 1 #!/usr/bin/python 2 print "hello world" 2.字节代码:python源文件经编译 ...

  8. python - web自动化测试 - 元素操作 - 窗口切换

    # -*- coding:utf-8 -*- ''' @project: web学习 @author: Jimmy @file: 元素操作-切换.py @ide: PyCharm Community ...

  9. springboot生成表结构

    https://blog.csdn.net/yalishadaa/article/details/59656332

  10. 如何在乌班图上配置java开发环境

    不想说的那么细,每条命令都说一下,在现在这个浮躁的时代,很少有人能看的下去,我就直接上命令,最简单的快捷的方式. 1:安装软件 2:设置root密码 3:配置mysql远程登录 4:安装java运行环 ...