BZOJ2301 [HAOI2011]Problem b
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
Description
Input
第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k
Output
共n行,每行一个整数表示满足要求的数对(x,y)的个数
Sample Input
2 5 1 5 1
1 5 1 5 2
Sample Output
3
HINT
100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000
正解:线性筛+莫比乌斯函数+分块
解题报告:
这道题是一道莫比乌斯函数的入门题,我从昨晚一直看题解和分析,直到今天才完全弄懂。系统性地写一份解题报告吧。
ps:我在学习的时候参考了这些论文与博客,贴出来以供参考吧:
http://wenku.baidu.com/view/fbe263d384254b35eefd34eb.html
http://wenku.baidu.com/view/fbec9c63ba1aa8114431d9ac.html
http://www.cnblogs.com/zhsl/p/3269288.html
可以发现题目要求的是∑ ∑ [gcd(i,j)==k] (1<=i<=n && 1<=j<=m),这样一个东西。(至于区间的话我们很快可以发现根据容斥原理[a,b]和[c,d]组合起来的答案就等于[1,b]组合[1,d] - [1,a-1]组合[1][d] - [1][b]组合[1][c-1] + [1][a-1] 组合 [1][c-1],问题从而转化。)但是直接求的复杂度很高,还是多组询问,肯定会TLE。
题目所求的可以变成
∑ ∑ [gcd(i,j)==1] (1<=i<=n/k && 1<=j<=m/k) ,相当于是同时除以k;
考虑再把式子变形:
∑ ∑ ∑ μ(d) (1<=i<=n && 1<=j<=m && d|gcd(i,j));
根据莫比乌斯函数的性质,当n=1时,∑μ(i)=1(1<=i<=n);否则∑μ(i)=0(1<=i<=n),所以实际上只有在gcd(i,j)==1时上式才有贡献。可是复杂度还是没有改变啊。我看了一篇解题报告,里面对于这个问题讲的很详细,大概是说根据容斥原理,可以把1<=i<=n && 1<=j<=m且满足gcd(i,j)==k的方案数转化成1<=i<=n && 1<=j<=m且满足gcd(i,j)>=k的方案数。二者的联系就在于莫比乌斯函数。论文里面画了一个图,一目了然地展示了二者的联系。

可以根据莫比乌斯函数的性质很快反应过来二者的联系。
所以得到新式:
ans=∑μ(i)*[n/i]*[m/i] (1<=i<=min(n,m),[n/i]表示n/i下取整)
容易发现这个式子可以使我的复杂度降低到O(n),但是询问次数也是5w级别,还是会TLE。考虑继续优化上式,考虑到[n/i]、[m/i]都会有大量的完全相等的部分,我们可以把[n/i]、[m/i]都相等的部分放在一起算,也就是一个分块的思想。容易发值为[n/i]的起点是i,终点是n/([n/i]),而取值不会超过根号n种,也就是说我只要算根号次。但是因为是两个都要相等,在数轴上画线段可以发现,这样的话总取值不会超过2×根号n种(论文里面也有图说明)。所以复杂度降低到可以接受的范围内。
值得一提的是,由于我们是分块计算的,所以我们必须要预处理出莫比乌斯函数和他的前缀和。预处理的方式是根据莫比乌斯函数的性质,进行一次线性筛。在筛出质数的同时随便求一下莫比乌斯函数,比较巧妙,然后直接构前缀和就可以了。
//It is made by ljh2000
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
const int inf = (<<);
const int MAXN = ;
const int MAXL = ;
LL a,b,c,d,k,ans;
int prime[MAXN],cnt;
bool ok[MAXN];
int mobius[MAXN],sum[MAXN];//莫比乌斯函数及其前缀和 inline int getint()
{
int w=,q=; char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar(); if(c=='-') q=,c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar(); return q ? -w : w;
} inline void init(){//递推得到莫比乌斯函数
//1的莫比乌斯函数是1;质数的莫比乌斯函数为1;含有相同质因子的数莫比乌斯函数为0;
//不含有相同质因子的数的莫比乌斯函数函数为(-1)^k,k为质因子个数
mobius[]=;
for(int i=;i<=MAXL;i++) {
if(!ok[i]) {
mobius[i]=-;
prime[++cnt]=i;
}
for(int j=;j<=cnt && i*prime[j]<=MAXL;j++) {
ok[i*prime[j]]=;//标记合数
if(i%prime[j]) mobius[i*prime[j]]=-mobius[i];//互质的两个数乘起来得到一个不含有相同质因子的数,质因子个数奇偶性改变,莫比乌斯函数变号
else { mobius[i*prime[j]]=; break; }//留到后面再筛,此处已经可以break
}
}
for(int i=;i<=MAXL;i++) sum[i]=sum[i-]+mobius[i];//求莫比乌斯函数的前缀和
} inline LL solve(LL n,LL m){//计算a在[1,n]且b在[1,m]中的gcd(a,b)==1的数目
n/=k; m/=k;
if(n>m) swap(n,m); if(n==) return ;
LL i,next1,next2,next;//把相等的部分直接分块一起计算
LL tot=;
for(i=;i<=n;i=next) {
next1=n/(n/i); next2=m/(m/i);
next=min(next1,next2);
tot+=(n/i)*(m/i)*(sum[next]-sum[i-]);
next++;
}
return tot;
} inline void work(){
int T=getint(); init();
while(T--) {
a=getint(); b=getint(); c=getint(); d=getint(); k=getint();
ans=solve(b,d)-solve(a-,d)-solve(b,c-)+solve(a-,c-);//容斥原理
printf("%lld\n",ans);
}
} int main()
{
work();
return ;
}
BZOJ2301 [HAOI2011]Problem b的更多相关文章
- BZOJ2301: [HAOI2011]Problem b[莫比乌斯反演 容斥原理]【学习笔记】
2301: [HAOI2011]Problem b Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 4032 Solved: 1817[Submit] ...
- Bzoj-2301 [HAOI2011]Problem b 容斥原理,Mobius反演,分块
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2301 题意:多次询问,求有多少对数满足 gcd(x,y)=k, a<=x<=b ...
- 【数论】【莫比乌斯反演】【线性筛】bzoj2301 [HAOI2011]Problem b
对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. 100%的数据满足:1≤n≤50000,1≤a≤b ...
- bzoj2301 [HAOI2011]Problem b【莫比乌斯反演 分块】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2301 很好的一道题.首先把每个询问转化为4个子询问,最后的结果就是这四个子询问的记过加加减减 ...
- 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的, ...
- [bzoj2301: [HAOI2011]Problem b] 乞讨
</pre><pre code_snippet_id="507886" snippet_file_name="blog_20141104_2_53831 ...
- bzoj2301: [HAOI2011]Problem b懵逼乌斯反演
属于结果的和好求但是结果不好求的题 (轻易能得到以k的倍数为最大公约数的对数,但是不好直接求k) 所以一波反演结束 其实反演的时候完全没有反演的感觉,就是不停地恒等变形 算是懵逼乌斯反演最简单的例题 ...
- [luogu2522][bzoj2301][HAOI2011]Problem b【莫比乌斯反演】
传送门:https://www.luogu.org/problemnew/show/P2522 题目描述 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y ...
- 题解【bzoj2301 [HAOI2011]Problem b】
Description 求有多少个数对 \((x,y)\) ,满足$ a \leq x \leq b$ ,\(c \leq y \leq d\) ,且 \(\gcd(x,y) = k\),\(\gcd ...
随机推荐
- Java数据类型和变量
Java中存在2种数据类型,下面我们来详解一下: 基本数据类型: 引用数据类型: 可以用一张表来记录: 基本数据类型 整型 byte:1个字节8位,取值范围为:[-128, 127],直接写值:(by ...
- shenben语录
1.别让别人的一句话将你击垮! 2.任何人都不能替你做决定,除了你自己! 3.对于省选: 想去就去,文化课什么的都不是问题. 如果不去,二十年后的自己一定会后悔的.
- 2016古装动作喜剧《笨贼别跑》HD720P.国语中字
导演: 雷金克编剧: 郭卫鹏 / 李诗怡 / 马强主演: 彭波 / 李添诺 / 董向荣 / 韩丰 / 董怡君类型: 喜剧 / 动作 / 古装制片国家/地区: 中国大陆语言: 汉语普通话上映日期: 20 ...
- (一)GATT Profile和GAP 简介(目前所有的BLE应用都基于GATT,所以也要了解是怎么一回事)-转发
个人大总结:(先后顺序) 1.GAP协议定义多个角色(其中就有中心设备[GATT客户端](唯一)叫主设备||和外围设备[GATT服务端端](多个)也叫从设备). 2.先经过GAP协议,再有GATT协议 ...
- 【跟着子迟品underscore】从用 `void 0` 代替 `undefined` 说起
Why underscore 最近开始看 underscore源码,并将 underscore源码解读 放在了我的 2016计划 中. 阅读一些著名框架类库的源码,就好像和一个个大师对话,你会学到很多 ...
- hystrix-turbine 监控的使用
1. 概述 Demo地址:http://git.oschina.net/zhou666/spring-cloud-7simple/tree/master/cloud-hystrix-turbine ...
- .Net简单图片系统-本地存储和分布式存储
本地存储 所谓本地存储就是将上传图片保存到图片服务器的本地磁盘上. if (ConfigHelper.GetConfigString("SaveMode") == "Lo ...
- TextBoxFor控件的扩展---Bootstrap在mvc上的应用
TextBoxFor控件的问题: 1:自带了样式,再用bootstrap样式会有冲突. 2:要加水印,js事件,限制输入长度比较麻烦. 因此需要对textboxfor控件进行扩展. 目标: 1:能使用 ...
- Windows Phone 8 显示当前项目的使用内存,最大峰值,最大内存上限
public static class MemoryDiagnosticsHelper { public static bool isStart = false; static Popup popup ...
- SQLite常用点滴总结(转)
expressionexpr ::= expr binary-op expr |expr [NOT] like-op expr [ESCAPE expr] |unary-op expr |( ...