博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【莫比乌斯反演】BZOJ1101 [POI2007]zap
阅读量:5348 次
发布时间:2019-06-15

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

Description

  回答T组询问,有多少组gcd(x,y)=d,x<=a, y<=b。T, a, b<=4e5。

 

Solution

  显然对于gcd=d的,应该把a/d b/d,然后转为gcd=1计算

  计算用莫比乌斯反演相信大家都会

  关键是有T组询问n^2会T

  于是有这样一个优化可以做到每次sqrt(n)

  

  每一次是ret+=mu[i]*(n/i)*(m/i)

  可是除法向下取整所以会导致很多i的(n/i)*(m/i)一样

  具体来说,向下取整得到的结果一定是约数所以对于(n/i)最多2sqrt(n)种

  那么(n/i)*(m/i)放一起也就4sqrt(n)种

  这个序列一定是不上升的,所以考虑对所有的(n/i)*(m/i)视为一块相同的一起算

  那么肯定要记录下mu[i]的前缀和

  如何快速得到每一块的l和r?

  每一块的r肯定要么n%i==0要么m%i==0

  于是用pos=min(n/(n/i),m/(m/i)) 定位

  当然pos+1就是下一块的l了

 

Code

1 #include
2 #include
3 #include
4 using namespace std; 5 const int maxn=5e4+5; 6 7 int flag[maxn],prime[maxn],cnt; 8 int mu[maxn],sum[maxn]; 9 10 int getmu(){11 mu[1]=1;12 for(int i=2;i
m) swap(n,m);33 for(int i=1;i<=n;i=pos+1){34 pos=min(n/(n/i),m/(m/i));35 ret+=(sum[pos]-sum[i-1])*(n/i)*(m/i);36 }37 return ret;38 }39 40 int main(){41 int T,a,b,d;42 scanf("%d",&T);43 getmu();44 45 while(T--){46 scanf("%d%d%d",&a,&b,&d);47 a/=d,b/=d;48 printf("%d\n",cal(a,b));49 }50 return 0;51 }

 

转载于:https://www.cnblogs.com/xkui/p/4596660.html

你可能感兴趣的文章
Luogu P1141 01迷宫【搜索/dfs】By cellur925
查看>>
js onclick事件传参
查看>>
WiCloud 商业Wi-Fi管理平台
查看>>
团队项目--未完待续
查看>>
双重标准,我该怎么解决
查看>>
python中的网页标签等字符处理
查看>>
Mybatis输入类型和结果类型
查看>>
Linux常用命令(五)
查看>>
Linux常用命令(四)
查看>>
Linux常用命令(六)
查看>>
Linux常用命令(六)
查看>>
Linux常用命令(八)
查看>>
Linux常用命令(七)
查看>>
Linux常用命令(九)
查看>>
Linux常用命令(十一)
查看>>
Linux常用命令(十)
查看>>
实验吧之这就是一个坑
查看>>
Linux常用命令(十二)
查看>>
Linux常用命令(十三)
查看>>
Linux常用命令(十五)
查看>>