题意

给定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. PLC状态机编程第五篇-状态机自动生成PLC程序

    这篇比较简单了,我就直接上图了,不多废话. 一.选择求解器,一定要选择定步长的. 二.右击Chart状态机,出现图上菜单 三.左边红色的勾选择,选择右侧的菜单,然后点击Generate Code按钮, ...

  2. 笔记-twisted

    笔记-twisted 1.      简介 Twisted is an event-driven networking engine written in Python and licensed un ...

  3. Android面试收集录6 事件分发机制

    转自:秋招面试宝典. 一. 基础认知 1.1 事件分发的对象是谁? 答:事件 当用户触摸屏幕时(View或ViewGroup派生的控件),将产生点击事件(Touch事件). Touch事件相关细节(发 ...

  4. 8,实例化Flask的参数 及 对app的配置

    Flask 是一个非常灵活且短小精干的web框架 , 那么灵活性从什么地方体现呢? 有一个神奇的东西叫 Flask配置 , 这个东西怎么用呢? 它能给我们带来怎么样的方便呢? 首先展示一下: from ...

  5. Android toolbar menu 字体点击样式

    今天在做toolbar的时候,右边的菜单的点击事件,就是文字,然后文字的样式,文字的大小,文字的颜色,高了半天.最后发现,文字点下去之后是有样式的,也就是按下去有阴影. 哥哥的耐心好,就知道这不是问题 ...

  6. wireshark 获取RTP payload

    wireshark 抓包获取RTP TS流数据,保存为TS文件 首先解析RTP流 2.点击菜单栏[Statistics]-[RTP]-[Show All Streams] 3.在Wireshark:R ...

  7. CSS UNIT 详解以及最佳实践

    分类 ■    绝对长度(Absolute units):cm,mm,in,pt,pc 绝对单位之间的换算:1in = 2.54cm=25.4mm=72pt=6pc 绝对长度在css中的表现和其他地方 ...

  8. Python全栈工程师(Linux基本操作)

    ParisGabriel         Python 入门基础        Linux :Ubuntu操作系统   首先我们说的是Linux操作系统常用的快捷键以及终端命令   一. VMware ...

  9. 孤荷凌寒自学python那些事第一天

    孤荷凌寒自学python第一天 初识python (学习过程的完整录像分享链接在文末,手写笔记图片在文末) 一种编程语言,首先是它的语言的基本架构,python总体让人耳目一新: 今天其实只接触到了它 ...

  10. Qt Creator : Read an image from resources

    最近两周碰到的一个问题是: opencv无法读取qt中的资源文件. 参考网址:https://stackoverflow.com/questions/45233559/qt-creator-read- ...