博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 2820: YY的GCD [莫比乌斯反演]【学习笔记】
阅读量:5076 次
发布时间:2019-06-12

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

2820: YY的GCD

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 1624  Solved: 853
[][][]

Description

神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对kAc这种
傻×必然不会了,于是向你来请教……多组输入

Input

第一行一个整数T 表述数据组数接下来T行,每行两个正整数,表示N, M

Output

T行,每行一个整数表示第i组数据的结果

Sample Input

2
10 10
100 100

Sample Output

30
2791

HINT

T = 10000

N, M <= 10000000


 

和bzoj2705很像http://www.cnblogs.com/candy99/p/6200745.html

但是n和m不同,不能使用直接欧拉函数的方法

 

参考:http://blog.csdn.net/acdreamers/article/details/8542292 && popoqqq课件

和上一题相同的函数:

  为满足的对数

  为满足的对数

显然,反演后得到

 

可以枚举每一个质数,套用上一题的做法,p相当于k,d*p也就是p的倍数了...很像上一题我WT1中的式子

 

其实d只要枚举到min(n,m)/p

然而复杂度承受不了,大约n/logn*sqrt(n)

我们设,那么继续得到

 

为什么这么做呢?因为这样之后发现F函数与p和d无关了,(要不然枚举p和d也是枚举了T)

可以提到前面,剩下的那一块可以处理前缀和做到O(1),前面再用除法分块,做到O(sqrt(n))

 

WT:

如何求g(T)=Σ{p|T && isprime(p)}miu(T/p)

法1.

只需要枚举每个素数,将他的倍数的g更新就可以了

由于有1/1+1/2+1/3+...+1/n=O(logn)这个结论 因此每个质数枚举时是均摊O(logn)的(*n后好想,是nlogn,但是质数只有n/logn个)

而质数恰好有O(n/logn)个 因此暴力枚举就是O(n)的

法2.

线性筛

g[i*p[j]]

当p[j]|i时结果显然为miu(i)

否则考虑mu(i*p[j]/pp),当p[j]=pp时为mu[i],p[j]!=pp时的所有的和就是-g(i),所以总的结果为mu(i)-g(i)

 枚举质数 4176ms

#include 
#include
#include
#include
#include
using namespace std;typedef long long ll;const int N=1e7+5;inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){
if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f;}int n,m;bool notp[N];int p[N],mu[N],g[N];void sieve(){ mu[1]=1; for(int i=2;i
m) swap(n,m); ll ans=0;int r; for(int i=1;i<=n;i=r+1){ r=min(n/(n/i),m/(m/i)); ans+=(ll)(g[r]-g[i-1])*(n/i)*(m/i); } return ans;}int main(int argc, const char * argv[]) { sieve(); int T=read(); while(T--){ n=read();m=read(); printf("%lld\n",cal(n,m)); } return 0;}

 线性筛:3328ms

 

#include 
#include
#include
#include
#include
using namespace std;typedef long long ll;const int N=1e7+5;inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){
if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f;}int n,m;bool notp[N];int p[N],mu[N],g[N];void sieve(){ mu[1]=1; for(int i=2;i
m) swap(n,m); ll ans=0;int r; for(int i=1;i<=n;i=r+1){ r=min(n/(n/i),m/(m/i)); ans+=(ll)(g[r]-g[i-1])*(n/i)*(m/i); } return ans;}int main(int argc, const char * argv[]) { sieve(); int T=read(); while(T--){ n=read();m=read(); printf("%lld\n",cal(n,m)); } return 0;}

 

 

 

转载于:https://www.cnblogs.com/candy99/p/6209609.html

你可能感兴趣的文章
复习文件操作
查看>>
SQL Server 使用作业设置定时任务之一(转载)
查看>>
第二阶段冲刺-01
查看>>
BZOJ1045 HAOI2008 糖果传递
查看>>
JavaScript 克隆数组
查看>>
eggs
查看>>
一步步学习微软InfoPath2010和SP2010--第七章节--从SP列表和业务数据连接接收数据(4)--外部项目选取器和业务数据连接...
查看>>
oracle 报错ORA-12514: TNS:listener does not currently know of service requested in connec
查看>>
基于grunt构建的前端集成开发环境
查看>>
利用循环播放dataurl的视频来防止锁屏:NoSleep.js
查看>>
python3 生成器与迭代器
查看>>
java编写提升性能的代码
查看>>
Abstract Factory Pattern
查看>>
list 容器 排序函数.xml
查看>>
《Genesis-3D开源游戏引擎完整实例教程-跑酷游戏篇03:暂停游戏》
查看>>
CPU,寄存器,一缓二缓.... RAM ROM 外部存储器等简介
查看>>
windows下编译FreeSwitch
查看>>
git .gitignore 文件不起作用
查看>>
Alan Turing的纪录片观后感
查看>>
c#自定义控件中的事件处理
查看>>