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

BZOJ.2705.[SDOI2012]Longge的问题(莫比乌斯反演 欧拉函数)

题目链接

\(Description\)

  求$$\sum_{i=1}^n\gcd(i,n)$$

\(Solution\)

\[ \begin{aligned} \sum_{i=1}^n\gcd(i,n) &=\sum_{d=1}^nd\sum_{i=1}^n[\gcd(i,n)=d]\\ &=\sum_{d=1}^nd\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}[\gcd(i,\lfloor\frac{n}{d}\rfloor)=1] \end{aligned} \]

  后一项不需要再化了,因为就是\(\phi(\lfloor\frac{n}{d}\rfloor)\)
  所以

\[\sum_{i=1}^n\gcd(i,n)=\sum_{d=1}^nd*\phi(\lfloor\frac{n}{d}\rfloor) \]

  因为\(\gcd(i,n)\mid n\),所以

\[ \begin{aligned} \sum_{i=1}^n\gcd(i,n) &=\sum_{d=1}^nd*\phi(\lfloor\frac{n}{d}\rfloor)\\ &=\sum_{d\mid n}d*\phi(\lfloor\frac{n}{d}\rfloor) \end{aligned} \]

  约数可以\(O(\sqrt{n})\)枚举,\(\phi\)可以\(O(\sqrt{n})\)求,复杂度为\(因子个数*\sqrt{n}\)

//928kb	56ms
//注意d!
#include <cmath>
#include <cstdio>
typedef long long LL;
const int N=1<<16;

int cnt,P[N>>3];
LL n;
bool Not_p[N+3];

void Make_Table(int N)
{
	for(int i=2; i<=N; ++i)
	{
		if(!Not_p[i]) P[++cnt]=i;
		for(int j=1; j<=cnt&&i*P[j]<=N; ++j)
		{
			Not_p[i*P[j]]=1;
			if(!(i%P[j])) break;
		}
	}
}
LL Phi(LL x)
{
	LL res=1;
	for(int i=1; i<=cnt&&1ll*P[i]*P[i]<=x; ++i)
		if(!(x%P[i]))
		{
			x/=P[i], res*=(P[i]-1);
			while(!(x%P[i])) x/=P[i], res*=P[i];
		}
	if(x>1) res*=x-1;
	return res;
}

int main()
{
	scanf("%lld",&n);
	Make_Table(sqrt(n)+1);
	LL res=0;
	int lim=sqrt(n);
	for(int i=1,lim=sqrt(n); i<=lim; ++i)
		if(!(n%i)) res+=1ll*i*Phi(n/i)+1ll*(n/i)*Phi(i);//!
	if(1ll*lim*lim==n) res-=lim*Phi(lim);
	printf("%lld",res);

	return 0;
}
posted @ 2018-04-08 16:41  SovietPower  阅读(158)  评论(0编辑  收藏  举报