HDU 5341 Gcd and Lcm


题意:给你一个N,让你求i=1nj=1nk=1nl=1nlcm(gcd(i,j),gcd(k,l))


参考论文:贾志鹏线性筛


首先,考虑子问题,求这样一个东西:i=1nj=1n[(i,j)=d]


(中括号是一个函数:若其中的命题为真,返回1,否则返回0)


转化一下,就是求1到n/d两两之间互素的数然后再乘以d就是gcd为d的数了。


即:i=1nj=1n[(i,j)=d] = 、/123​i=1n/dj=1n/d[(i,j)=1]


那么如题意所说,窝们可以定义一个函数 f(x)=、/123​i=1xj=1x[(i,j)=1]


那么对于固定的n,窝们求gcd为x的个数为f(n/x)。


那么问题就变成了


ans=、/123​i=1nj=1nlcm(i,j)*f(n/i)*f(n/j)


令p=gcd(i,j),则ans=p=1ni=1n/pj=1n/ppijf(n/(i*p))f(n/(j*p))[(i,j)=1]


ans=p=1ni=1n/pj=1n/ppijf(n/(i*p))f(n/(j*p))d|gcd(i,j)u(d)


=p=1ni=1n/pj=1n/ppijf(n/(i*p))f(n/(j*p))d|i&&d|ju(d)


其中u(d)表示莫比乌斯函数,然后窝们想方设法将u(d)提到前面来:


=p=1n​  p*du(d)i=1n/p/d​   (i*d)*f(n/(i*d*p))j=1n/p/d​  (j*d)*f(n/(j*d*p))


可以将ij视为相同的两个东西,同时把d提出来放到前面:


=p=1n​  du(d)*p*d*d*(i=1n/p/d​   i*f(n/(i*d*p)))2 


然后,利用类似于参考论文中贾志鹏处理的方法,令t=p*d


=、/123​t=1n(i=1n/t​   i*f(n/(i*t)))2* t*d|tu(d)*d


h(t)=t*d|tu(d)*d 是一个积性函数,窝们可以用线性筛的思想去O(n)的预处理出所有的h。


g(x)=i=1x​  i*f(x/i) 并不是一个积性函数但是x/i一共有大概sqrt(x)种取值。


在这里窝们可以用一种方法处理复杂度为sqrt(x),详细可以看代码。


那么ans=、/123​t=1ng(n/t)2*h(t)


同理,n/t也是只有sqrt(n)种取值,所以复杂度最大也不超过sqrt(n)*sqrt(n)<=n,最后的复杂度不超过O(n)。


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define Msn(x,y) (memset((x),0,sizeof((x[0]))*(y+1)))
#define msn(x) (memset((x),0,sizeof((x))))
#define msx(x,y) (memset((x),0x7f,sizeof((x[0]))*(y+3)))
#define fuck(x) cerr << #x << " <- " << x << endl
#define acer cout<<"sb"<


​ssfasdfasdfasdfasdfasdf

你可能感兴趣的:(数论,tricks)