【莫比乌斯反演】【bzoj2301】problem b
2015-07-01 21:31
399 查看
f(i)x∈[1,n],y∈[1,m],所有gcd=i的点对的数量,我们发现并不好求,于是再设F(i)x∈[1,n],y∈[1,m],所有满足i整除gcd(x,y)的点对的数量 ,F显然就是(n/i)(m /i),f根据莫比乌斯反演+gcd化为1简化一下,枚举倍数就变成了1到n/k啦,然后就用下标分块优化就可以求啦
[code]#include<cstdio> #include<cstring> #define maxl 500001 int a,b,c,d,k,ans; int no[maxl],p[maxl],mu[maxl],sum[maxl]; void prework() { scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); } void shai() { no[1]=1;mu[1]=1; for(int i=2;i<=maxl;i++) { if(!no[i]) p[++p[0]]=i,mu[i]=-1; int j=1,t=p[1]*i; while(j<=p[0] && t<=maxl) { no[t]=1; if(i%p[j]==0) { mu[t]=0; break; } mu[t]=-mu[i]; t=p[++j]*i; } } for(int i=1;i<=maxl;i++) sum[i]=sum[i-1]+mu[i]; } int min(int x,int y) { if(x<y) return x; else return y; } int f(int n,int m) { n=n/k,m=m/k; if(n>m){int t=n;n=m;m=t;} int ret=0,pos; for(int i=1;i<=n;i=pos+1) { pos=min(n/(n/i),m/(m/i)); ret+=(n/i)*(m/i)*(sum[pos]-sum[i-1]); } return ret; } void mainwork() { ans=f(b,d)-f(a-1,d)-f(c-1,b)+f(a-1,c-1); } void print() { printf("%d\n",ans); } int main() { int t; scanf("%d",&t); shai(); while(t--) { prework(); mainwork(); print(); } return 0; }
相关文章推荐
- 第5天-sql计算字段的创建与基础函数的使用
- [Books] 《JavaScript权威指南》 -- #1~5
- 进程与线程浅析
- Stanford UFLDL教程 反向传播算法(BP算法)
- OCR File and Voting Disk Administration by Example - (Oracle 10g)
- ROS安装USB摄像头
- [Leetcode]-Min Stack
- Struts2文件上传,以及各种注意事项
- halcon一维测量
- c#语言
- Linux命令-查看进程命令:pstree
- Objective-C 深拷贝与浅拷贝
- Complete The Pattern #2
- 斯坦福大学UFLDL教程列表
- Failed to locate the winutils binary in the hadoop binary path
- 2014 软件测试发展汇总与展望
- python3爬虫
- UITextView+Button
- GIT 提交流程
- [转载]磁盘概念 (2011-09-20 10:00:54)