BZOJ 2301 [HAOI2011]Problem b (容斥+莫比乌斯反演+分块优化 详解)

本文主要是介绍BZOJ 2301 [HAOI2011]Problem b (容斥+莫比乌斯反演+分块优化 详解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


2301: [HAOI2011]Problem b

Time Limit: 50 Sec  Memory Limit: 256 MB
Submit: 2096  Solved: 909
[Submit][Status][Discuss]

Description

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

Input

第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k

Output

共n行,每行一个整数表示满足要求的数对(x,y)的个数

Sample Input

2

2 5 1 5 1

1 5 1 5 2

Sample Output

14

3

HINT

100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000


题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2301


题目分析:首先n就是五万,因此每次即使是O(n)的计算总的下来也是O(n^2)了,因此对于每次操作我们要让时间复杂度小于O(n),题意很清楚

先将原式变形:

a / k <= x / k <= b / k,c / k <= y / k <= d / k,gcd(x / k, y / k) = 1,令cal(b / k,d / k)为1 <= x / k <= b / k,1 <= y / k <= d / k时取出的满足条件的个数,则根据容斥原理有

ans = cal(b / k,d / k) - cal((a - 1) / k,d / k) - cal((c - 1) / k,b / k) + cal((a - 1) / k,(c - 1) / k),因为1~a-1和1~c-1都不在我们所求的范围内,又减的时候这段区间减了两次,因此要再加上一个,接下来看cal函数,这里要用到分块求和,如果不做优化,就是直接枚举公约数ans += mob[i] * (l / i) * (r / i)但这样会超时,考虑到不能整除的特性,在很大一段区间内(l / i)和(r / i)的值是相同的,举个简单的例子,l = 10,r  =  11那么可以看出 i从6到10,l / i和r / i的值都是1,因此考虑分块求和,从i开始最长的相等区间长度为min(l / (l / i),r / (r / i)),这里如果不能理解的话,比如l / (l / i),设l / i = p,p表示整除时的值,那么l / p就是从i开始整除值为p的个数了

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int const MAX = 50005;
int p[MAX], mob[MAX], sum[MAX];
bool prime[MAX];
int a, b, c, d, k;void Mobius()
{int pnum = 0;memset(prime, true, sizeof(prime));memset(sum, 0, sizeof(sum));mob[1] = 1;sum[1] = 1;for(int i = 2; i < MAX; i++){if(prime[i]){p[pnum ++] = i;mob[i] = -1;}for(int j = 0; j < pnum && i * p[j] < MAX; j++){prime[i * p[j]] = false;if(i % p[j] == 0){mob[i * p[j]] = 0;break;}mob[i * p[j]] = -mob[i];}sum[i] = sum[i - 1] + mob[i];}
}int cal(int l, int r)
{if(l > r)swap(l, r);int ans = 0;for(int i = 1, last = 0; i <= l; i = last + 1){last = min(l / (l / i), r / (r / i));ans += (l / i) * (r / i) * (sum[last] - sum[i - 1]);}return ans;
}int main()
{Mobius();int n;scanf("%d", &n);while(n --){scanf("%d %d %d %d %d", &a, &b, &c, &d, &k);int ans = 0;ans += cal(b / k, d / k);ans -= cal((a - 1) / k, d / k);ans -= cal((c - 1) / k, b / k);ans += cal((a - 1) / k, (c - 1) / k);printf("%d\n", ans);   }
}


这篇关于BZOJ 2301 [HAOI2011]Problem b (容斥+莫比乌斯反演+分块优化 详解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/829674

相关文章

Java注解之超越Javadoc的元数据利器详解

《Java注解之超越Javadoc的元数据利器详解》本文将深入探讨Java注解的定义、类型、内置注解、自定义注解、保留策略、实际应用场景及最佳实践,无论是初学者还是资深开发者,都能通过本文了解如何利用... 目录什么是注解?注解的类型内置注编程解自定义注解注解的保留策略实际用例最佳实践总结在 Java 编程

MySQL数据库约束深入详解

《MySQL数据库约束深入详解》:本文主要介绍MySQL数据库约束,在MySQL数据库中,约束是用来限制进入表中的数据类型的一种技术,通过使用约束,可以确保数据的准确性、完整性和可靠性,需要的朋友... 目录一、数据库约束的概念二、约束类型三、NOT NULL 非空约束四、DEFAULT 默认值约束五、UN

Python使用Matplotlib绘制3D曲面图详解

《Python使用Matplotlib绘制3D曲面图详解》:本文主要介绍Python使用Matplotlib绘制3D曲面图,在Python中,使用Matplotlib库绘制3D曲面图可以通过mpl... 目录准备工作绘制简单的 3D 曲面图绘制 3D 曲面图添加线框和透明度控制图形视角Matplotlib

MySQL中的分组和多表连接详解

《MySQL中的分组和多表连接详解》:本文主要介绍MySQL中的分组和多表连接的相关操作,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录mysql中的分组和多表连接一、MySQL的分组(group javascriptby )二、多表连接(表连接会产生大量的数据垃圾)MySQL中的

Java 实用工具类Spring 的 AnnotationUtils详解

《Java实用工具类Spring的AnnotationUtils详解》Spring框架提供了一个强大的注解工具类org.springframework.core.annotation.Annot... 目录前言一、AnnotationUtils 的常用方法二、常见应用场景三、与 JDK 原生注解 API 的

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

SpringBoot3.4配置校验新特性的用法详解

《SpringBoot3.4配置校验新特性的用法详解》SpringBoot3.4对配置校验支持进行了全面升级,这篇文章为大家详细介绍了一下它们的具体使用,文中的示例代码讲解详细,感兴趣的小伙伴可以参考... 目录基本用法示例定义配置类配置 application.yml注入使用嵌套对象与集合元素深度校验开发

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

Java Stream流使用案例深入详解

《JavaStream流使用案例深入详解》:本文主要介绍JavaStream流使用案例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录前言1. Lambda1.1 语法1.2 没参数只有一条语句或者多条语句1.3 一个参数只有一条语句或者多

SpringBoot整合mybatisPlus实现批量插入并获取ID详解

《SpringBoot整合mybatisPlus实现批量插入并获取ID详解》这篇文章主要为大家详细介绍了SpringBoot如何整合mybatisPlus实现批量插入并获取ID,文中的示例代码讲解详细... 目录【1】saveBATch(一万条数据总耗时:2478ms)【2】集合方式foreach(一万条数