博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【BZOJ3930】[CQOI2015] 选数(容斥)
阅读量:5366 次
发布时间:2019-06-15

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

大致题意: 让你求出在区间\([L,H]\)间选择\(n\)个数时,有多少种方案使其\(gcd\)\(K\)

容斥

原以为是一道可怕的。

但是,数据范围中有这样一句话:\(H-L\le10^5\)

于是,它就变成了一道可以用容斥乱搞的题目。

大致思路

首先,我们将\(L\)\(H\)分别除以\(K\)(注意\(L\)向上取整,\(H\)向下取整,这应该还是比较好理解的)。

然后我们在\([1,H-L]\)之间枚举\(i\),假设\(x\)表示\([L,H]\)区间内选出\(i\)的倍数的个数,则选择\(n\)个数使得这些数全部含有约数\(i\)的方案数应为\(x^n-x\)

那么如何求出最大公约数是\(i\)的方案数呢?

很简单,根据容斥原理,全是\(i\)倍数的方案数中多余的方案数应为最大公约数为\(2i,3i,4i,...\)的方案数,所以我们可以倒着求一遍,得出答案。

具体实现详见代码吧。

代码

#include
#define MOD 1000000007#define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))#define Dec(x,y) ((x-=(y))<0&&(x+=MOD))#define Delta 100000using namespace std;int n,k,l,r,f[Delta+5];inline int quick_pow(int x,int y,register int res=1)//快速幂{ for(;y;x=1LL*x*x%MOD,y>>=1) if(y&1) res=1LL*res*x%MOD; return res;}int main(){ register int i,j,x,y; for(scanf("%d%d%d%d",&n,&k,&l,&r),(l+=k-1)/=k,r/=k,i=1;i<=r-l;++i) x=(l+i-1)/i,y=r/i,f[i]=quick_pow(y-x+1,n),Dec(f[i],y-x+1);//求出含有约数i的方案数f[i] for(i=r-l;i;--i) for(j=i<<1;j<=r-l;j+=i) Dec(f[i],f[j]);//容斥,求出gcd为i的方案数f[i] return printf("%d",f[1]+(l==1)),0;//特判l=1的情况,将f加1}

转载于:https://www.cnblogs.com/chenxiaoran666/p/BZOJ3930.html

你可能感兴趣的文章
数据库第1,2,3范式学习
查看>>
《Linux内核设计与实现》第四章学习笔记
查看>>
Docker 安装MySQL5.7(三)
查看>>
CSS: caption-side 属性
查看>>
CSS3中box-sizing的理解
查看>>
mysql导入source注意点
查看>>
linux下编译安装nginx
查看>>
DLL 导出函数
查看>>
windows超过最大连接数解决命令
查看>>
12个大调都是什么
查看>>
angular、jquery、vue 的区别与联系
查看>>
Intellij idea创建javaWeb以及Servlet简单实现
查看>>
代理网站
查看>>
Open multiple excel files in WebBrowser, only the last one gets activated
查看>>
FFmpeg进行视频帧提取&音频重采样-Process.waitFor()引发的阻塞超时
查看>>
最近邻与K近邻算法思想
查看>>
【VS开发】ATL辅助COM组件开发
查看>>
FlatBuffers In Android
查看>>
《演说之禅》I &amp; II 读书笔记
查看>>
thinkphp3.2接入支付宝支付接口(PC端)
查看>>