博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
莫(meng)比(bi)乌斯反演--BZOJ2301: [HAOI2011]Problem b
阅读量:4608 次
发布时间:2019-06-09

本文共 2478 字,大约阅读时间需要 8 分钟。

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)求和。

入门题。

1 #include
2 #include
3 #include
4 //#include
5 #include
6 //#include
7 using namespace std; 8 9 int a,b,c,d,K,T;10 11 #define maxn 5001112 int miu[maxn],prime[maxn],lp=0,summiu[maxn]; bool notprime[maxn];13 void pre(int n=50001)14 {15 miu[1]=summiu[1]=1;16 for (int i=2;i<=n;i++)17 {18 if (!notprime[i]) {prime[++lp]=i; miu[i]=-1;}19 summiu[i]=summiu[i-1]+miu[i];20 for (int j=1;j<=lp && 1ll*i*prime[j]<=n;j++)21 {22 notprime[i*prime[j]]=1;23 if (i%prime[j]) miu[i*prime[j]]=-miu[i];24 else {miu[i*prime[j]]=0; break;}25 }26 }27 }28 29 #define LL long long30 LL solve(int p,int q)31 {32 LL ans=0;33 for (int i=1,last,to=min(p,q);i<=to;i=last+1)34 {35 last=min(p/(p/i),q/(q/i));36 ans+=1ll*(p/i)*(q/i)*(summiu[last]-summiu[i-1]);37 }38 return ans;39 }40 41 int main()42 {43 pre();44 scanf("%d",&T);45 while (T--)46 {47 scanf("%d%d%d%d%d",&a,&b,&c,&d,&K);48 printf("%lld\n",solve(b/K,d/K)-solve((a-1)/K,d/K)-solve(b/K,(c-1)/K)+solve((a-1)/K,(c-1)/K));49 }50 return 0;51 }
View Code

 

转载于:https://www.cnblogs.com/Blue233333/p/8157770.html

你可能感兴趣的文章
[Selenium+Java] Desired Capabilities in Selenium
查看>>
创建Visual studio项目模板 vstemplate关键点纪要
查看>>
工作4年的老腊肉的总结
查看>>
转: 详解css中的display属性
查看>>
主导2015年的网页设计趋势
查看>>
对象转数组并倒序
查看>>
aspx页面中写if else 语句的方法,
查看>>
VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNTION(翻译)
查看>>
UVA 10539 - Almost Prime Numbers 素数打表
查看>>
Laravel核心之IOC和Facade 架构分析1
查看>>
C++ 的输出格式
查看>>
好用的XML序列,简单接口
查看>>
高德室内地图解析
查看>>
python学习5
查看>>
面试经验谈(经典)
查看>>
Linux上面缺少rz和sz命令
查看>>
ArcGIS Python编程 二
查看>>
rmmod出现的can't unload 'xxx': Device or resource busy错误
查看>>
[离散时间信号处理学习笔记] 5. 离散时间信号与系统的频域表示
查看>>
python文件基本操作
查看>>