博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

BZOJ.2820.YY的GCD(莫比乌斯反演)

题目链接

总感觉博客园的\(Markdown\)很。。\(gouzhi\),可以看这的


\(Description\)
  求$$\sum_{i=1}n\sum_{j=1}m[gcd(i,j)为质数]$$

\(Solution\)

\[ \begin{aligned} Ans &=\sum_{i=1}^n\sum_{j=1}^m[(i,j)为质数]\\ &=\sum_{p}\sum_{i=1}^n\sum_{j=1}^m[(i,j)=p]\\ &=\sum_{p}\sum_{i=1}^{\lfloor{\frac{n}{p}}\rfloor}\sum_{j=1}^{\lfloor{\frac{m}{p}}\rfloor}[(i,j)=1]\\ &=\sum_{p}\sum_{d=1}^{min(\lfloor{\frac{n}{p}}\rfloor,\lfloor{\frac{m}{p}}\rfloor)}\mu(d)\lfloor\frac{n}{pd}\rfloor\lfloor\frac{m}{pd}\rfloor \end{aligned} \]

  带着\(pd\)不舒服啊,令\(t=pd\),则

\[ \begin{aligned} Ans &=\sum_{p}\sum_{d=1}^{min(\lfloor{\frac{n}{p}}\rfloor,\lfloor{\frac{m}{p}}\rfloor)}\mu(d)\lfloor\frac{n}{pd}\rfloor\lfloor\frac{m}{pd}\rfloor\\ &=\sum_p\sum_{p|t}\mu(\frac{t}{p})\lfloor\frac{n}{t}\rfloor\lfloor\frac{m}{t}\rfloor\\ &=\sum_{t=1}^{min(n,m)}\lfloor\frac{n}{t}\rfloor\lfloor\frac{m}{t}\rfloor\sum_{p|t}\mu(\frac{t}{p}) \end{aligned} \]

  前面那部分好求,后面那部分如果能用前缀和求的话就容易了。事实上也是可以的。
  令\(F(t)=\sum_{p|t}\mu(\frac{t}{p})\),那么$$Ans=\sum_{t=1}^{min(n,m)}F(t)\lfloor\frac{n}{t}\rfloor\lfloor\frac{m}{t}\rfloor$$
  对于每个\(p\)我们只需要暴力枚举约数\(d\)更新\(F(pd)\)就可以了。
  复杂度(转自ppt by \(popoqqq\)):由$$\lim_{n\rightarrow\infty}\sum_{i=1}^n\frac{1}{i}=\ln n+r$$
  易知,每个质数更新时是均摊\(O(\log n)\)的,而质数个数恰好为\(O(\frac{n}{\log n})\),所以暴力枚举+维护前缀和的时间复杂度为\(O(n)\)
  计算复杂度自然就是\(O(\sqrt{n})\)了。

  另外\(F(t)=\sum_{p|t}\mu(\frac{t}{p})\)是可以一起线性筛出来的。参考

\[ F(p*k)= \begin{cases} \mu(k), & p\mid k\\ \mu(k)-F(k), & p\nmid k \end{cases} \]

  对于这个式子,\(F(p*k)=\sum_{p'|p*k}\mu(\frac{p*k}{p'})\)

  • \(p\mid k\)时,有\(p*k\)的因子\(p\)的次数\(\geq 2\)
      1.\(p'=p\)时,即\(\mu(k)\)
      2.\(p'\neq p\)时,因为\(p\)的次数\(\geq 2\),所以为\(0\)
      因此此时答案为\(\mu(k)\)
  • \(p\nmid k\)时,有\(p*k\)的质因子\(p\)的次数为\(1\)
      1.\(p'=p\)时,也是\(\mu(k)\)
      2.\(p'\neq p\)时,此时\(p'\)\(p\)互质,由\(\mu\)的积性函数性质,可化为\(\sum_{p'|k}\mu(\frac{k}{p'})\mu(p)\)\(\mu(p)=-1\),所以为\(-\sum_{p'|k}\mu(\frac{k}{p'})=-F(k)\)
      因此此时答案为\(\mu(k)-F(k)\)
      注意对于每个质数\(p\)\(F(p)=1\)\(F(1)=0\)

线性筛\(F(t)\)

//131680kb	3380ms
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=1e7+1;

int cnt,P[1000005],f[N+2],mu[N+2],sum[N+2];
bool Not_p[N+2];

void Make_Table()
{
	mu[1]=1;/*f[1]=0;*/
	for(int i=2; i<N; ++i)
	{
		if(!Not_p[i]) P[++cnt]=i,mu[i]=-1,f[i]=1;
		for(int j=1; j<=cnt&&i*P[j]<N; ++j)
		{
			Not_p[i*P[j]]=1;
			if(i%P[j]) mu[i*P[j]]=-mu[i], f[i*P[j]]=mu[i]-f[i];
			else {mu[i*P[j]]=0, f[i*P[j]]=mu[i]; break;}
		}
	}
	for(int i=1; i<N; ++i) sum[i]=sum[i-1]+f[i];
//	for(int i=1; i<=cnt; ++i)
//		for(int j=1; j*P[i]<N; ++j)
//			sum[j*P[i]]+=mu[j];
//	for(int i=2; i<N; ++i) sum[i]+=sum[i-1];
}

int main()
{
	Make_Table();
	int T,n,m; LL res;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m), res=0;
		if(n>m) std::swap(n,m);
		for(int nxt,i=1; i<=n; i=nxt+1)
		{
			nxt=std::min(n/(n/i),m/(m/i));
			res+=1ll*(sum[nxt]-sum[i-1])*(n/i)*(m/i);
		}
		printf("%lld\n",res);
	}
	return 0;
}

枚举约数:

//131680kb	4388ms
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=1e7+1;

int cnt,P[1000005],mu[N+2];
LL sum[N+2];
bool Not_p[N+2];

void Make_Table()
{
	mu[1]=1;
	for(int i=2; i<N; ++i)
	{
		if(!Not_p[i]) P[++cnt]=i,mu[i]=-1;
		for(int j=1; j<=cnt&&i*P[j]<N; ++j)
		{
			Not_p[i*P[j]]=1;
			if(i%P[j]) mu[i*P[j]]=-mu[i];
			else {mu[i*P[j]]=0; break;}
		}
	}
	for(int i=1; i<=cnt; ++i)
		for(int j=1; j*P[i]<N; ++j)
			sum[j*P[i]]+=mu[j];
	for(int i=2; i<N; ++i) sum[i]+=sum[i-1];
}

int main()
{
	Make_Table();
	int T,n,m; LL res;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m), res=0;
		if(n>m) std::swap(n,m);
		for(int nxt,i=1; i<=n; i=nxt+1)
		{
			nxt=std::min(n/(n/i),m/(m/i));
			res+=(sum[nxt]-sum[i-1])*(n/i)*(m/i);
		}
		printf("%lld\n",res);
	}
	return 0;
}
posted @ 2018-04-03 17:26  SovietPower  阅读(240)  评论(0编辑  收藏  举报