莫(meng)比(bi)乌斯反演--BZOJ2301: [HAOI2011]Problem b
n<=50000个询问,每次问a<=x<=b,c<=y<=d中有多少gcd(x,y)=K的(x,y)。a,b,c,d,K<=50000。
这大概是入门题辣。。这里记一波笔记
当难以计算f(i)而易于计算他的反演式g(i)时,可以通过计算g(i)->反演得到f(i)。
先放莫比乌斯函数的性质:$\sum_{d|i} \mu(d)=\left\{\begin{matrix} 1,i=1\\0,i>1\end{matrix}\right.$,$\sum_{d|i}(\mu(d)*n/d)=\varphi(i)$。
反演式一:$g(i)=\sum_{d|i} f(i) ------> f(i)=\sum_{d|i} \mu(d)g(i/d)$。
证明:$\sum_{d|i} \mu(d)g(i/d)=\sum_{d|i} \mu(d) \sum_{d_1|(i/d)} f(d_1)=\sum_{d|i} \sum_{d_1|(i/d)} \mu(d) f(d_1)$。
注意到$dd_1j=i$,所以对每一个$d=d_2$,$d_1=d_3$都有一个$d=d_3$,$d_1=d_2$与之对应。
所以$上式=\sum_{d|i} \sum{d_1|(i/d)} f(d) \mu(d_1)=\sum_{d|i} f(d) \sum{d_1|(i/d)} \mu(d_1)$,由莫比乌斯函数性质得$=f(i)$。
反演式二:$g(i)=\sum_{i|d} f(i) ------> f(i)=\sum_{i|d} \mu(d/i)g(d)$。
证明同上,略。
这题先容斥,变成问1<=x<=n,1<=y<=m中有多少(x,y)=K,由于(x,y)=K的充要条件是(x/K,y/K)=1,所以变成1<=x<=n/K,1<=y<=m/K中有多少(x,y)=1。
为什么这么变呢,因为假如题目求的是f(i),表示1<=x<=n,1<=y<=m中有多少(x,y)=i,那反演式g(i)表示1<=x<=n,1<=y<=m中有多少i|(x,y),g(i)和f(i)满足反演式2。
而明显的,$g(i)=(n/i)*(m/i)$,这里/是向下取整,所以$f(i)=\sum_{i|d} \mu(d/i)g(d)=\sum_{i|d} \mu(d/i)(n/d)(m/d)$。
这时可以发现(n/d)和(m/d)分别只有$2\sqrt(n)$和$2\sqrt(m)$种取值,把他俩分别叫a和b,而随着d增大a和b会缓慢增大,可能a增大b不变,b增大a不变,也可能a,b都增大,都不变。那么数对((n/d),(m/d))最多只有$2\sqrt(n)+2\sqrt(m)$个,因此(n/d)*(m/d)最多只有$2\sqrt(n)+2\sqrt(m)$种取值。
如果上面的i=1,那么只需要枚举这$2\sqrt(n)+2\sqrt(m)$个(n/d)*(m/d)的值就可以在根号时间内算出答案,因为一个(n/d)*(m/d)的值对应一段连续的d,如果i=1,就可以把连续一段莫比乌斯函数以前缀和来O(1)求和。
入门题。
#include<cstring>
#include<cstdlib>
#include<cstdio>
//#include<assert.h>
#include<algorithm>
//#include<iostream>
using namespace std; int a,b,c,d,K,T; #define maxn 50011
int miu[maxn],prime[maxn],lp=,summiu[maxn]; bool notprime[maxn];
void pre(int n=)
{
miu[]=summiu[]=;
for (int i=;i<=n;i++)
{
if (!notprime[i]) {prime[++lp]=i; miu[i]=-;}
summiu[i]=summiu[i-]+miu[i];
for (int j=;j<=lp && 1ll*i*prime[j]<=n;j++)
{
notprime[i*prime[j]]=;
if (i%prime[j]) miu[i*prime[j]]=-miu[i];
else {miu[i*prime[j]]=; break;}
}
}
} #define LL long long
LL solve(int p,int q)
{
LL ans=;
for (int i=,last,to=min(p,q);i<=to;i=last+)
{
last=min(p/(p/i),q/(q/i));
ans+=1ll*(p/i)*(q/i)*(summiu[last]-summiu[i-]);
}
return ans;
} int main()
{
pre();
scanf("%d",&T);
while (T--)
{
scanf("%d%d%d%d%d",&a,&b,&c,&d,&K);
printf("%lld\n",solve(b/K,d/K)-solve((a-)/K,d/K)-solve(b/K,(c-)/K)+solve((a-)/K,(c-)/K));
}
return ;
}
莫(meng)比(bi)乌斯反演--BZOJ2301: [HAOI2011]Problem b的更多相关文章
- bzoj2301: [HAOI2011]Problem b懵逼乌斯反演
属于结果的和好求但是结果不好求的题 (轻易能得到以k的倍数为最大公约数的对数,但是不好直接求k) 所以一波反演结束 其实反演的时候完全没有反演的感觉,就是不停地恒等变形 算是懵逼乌斯反演最简单的例题 ...
- BZOJ2301: [HAOI2011]Problem b[莫比乌斯反演 容斥原理]【学习笔记】
2301: [HAOI2011]Problem b Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 4032 Solved: 1817[Submit] ...
- 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
对于给出的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 —— 莫比乌斯反演+容斥原理
题意 给定a, b, c, d, k,求出: \[\sum_{i=a}^b\sum_{j=c}^d[gcd(i, j) = k]\] 题解 为方便表述,我们设 \[calc(\alpha, \beta ...
- bzoj2301 [HAOI2011]Problem b【莫比乌斯反演 分块】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2301 很好的一道题.首先把每个询问转化为4个子询问,最后的结果就是这四个子询问的记过加加减减 ...
- [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 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input 第一行一个整数 ...
- Bzoj-2301 [HAOI2011]Problem b 容斥原理,Mobius反演,分块
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2301 题意:多次询问,求有多少对数满足 gcd(x,y)=k, a<=x<=b ...
随机推荐
- QT入门学习
第一个QT程序 #include<QApplication> #include<QDialog> #include<QLabel> #include<QTex ...
- Python学习 Day 12 调试 断言 logging pdb pdb.set_trace
调试 第一种方法简单直接粗暴有效,就是用print把可能有问题的变量打印出来看看: >>> def foo(s): n= int(s) print '>>> n = ...
- iOS----轻松掌握AFN网络顶级框架
AFN 一.什么是AFN 全称是AFNetworking,是对NSURLConnection的一层封装 虽然运行效率没有ASI高,但是使用比ASI简单 在iOS开发中,使用比较广泛 AFN的githu ...
- Jvisualvm--JAVA性能分析工具
JDK自带的JAVA性能分析工具.它已经在你的JDK bin目录里了,只要你使用的是JDK1.6 Update7之后的版本.点击一下jvisualvm.exe图标它就可以运行了. 这里是VisualV ...
- C++ 多态、虚函数、虚析构函数
1.若某种语言只支持类但不支持多态,则只能称为基于对象,不能说是面向对象. 2.多态:向不同对象发送同一个消息,不同的对象会产生不同的行为,发送消息可以是调用函数等操作.函数重载.运算符重载都是多态. ...
- 数组,寻找第K大的数
时间复杂度 O(n) def partition(data,left,right): if (len(data)<=0 or left<0 or right>=len(data)): ...
- java实现搜索文件夹中所有文件包含的关键字的文件路径(递归搜索)
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io ...
- cc.Button
cc.Button 1:添加按钮的方法 (1)直接创建带Button组件的节点; (2)先创建节点,再添加组件;2:按钮组件, 按钮是游戏中最常用的组件, 点击然后响应事件;3: 按钮的过渡效果: ...
- group by两个条件
学生表: 成绩表: 问题:统计各系各门课程的平均成绩 答案: select sdept,cno,AVG(grade)avg_grade from S join SC on S.sno = SC.sno ...
- BZOJ 3144 切糕 最小割
题意: 一个矩阵,每个格子分配一个数,不同的数字,代价不同,要求相邻格子数字差小等于d 求最小代价. 分析: 我猜肯定有人看题目就想到最小割了,然后一看题面理科否决了自己的这个想法…… 没错,就是最小 ...