【XSY2719】prime 莫比乌斯反演

题目描述

  设\(f(i)\)\(i\)的不同的质因子个数,求\(\sum_{i=1}^n2^{f(i)}\)

  \(n\leq{10}^{12}\)

题解

  考虑\(2^{f(i)}\)的意义:有\(f(i)\)总因子,每种可以分给两个人中的一个。那么就有\(2^{f(i)}=\sum_{d|i}[\gcd(d,\frac{i}{d})=1]\)

  然后就是简单莫比乌斯反演了。

\[\begin{align} s&=\sum_{i=1}^n\sum_{d|i}[\gcd(d,\frac{i}{d})=1]\\ &=\sum_{i=1}^n\sum_{d|i}\sum_{j|d\text{&&}j|\frac{i}{d}}\mu(j)\\ &=\sum_{i=1}^n\sum_{j^2|i}g(\frac{i}{j^2})\mu(j)\\ &=\sum_{j=1}^\sqrt{n}\mu(j)\sum_{i=1}^{\lfloor\frac{n}{j^2}\rfloor}g(i)\\ &=\sum_{j=1}^\sqrt{n}\mu(j)\sum_{i=1}^{\lfloor\frac{n}{j^2}\rfloor}\lfloor\frac{n}{j^2i}\rfloor \end{align} \]

  时间复杂度:\(O(\sqrt n\log n)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll p=998244353;
ll gao(ll x)
{
	ll s=0;
	ll i,j;
	for(i=1;i<=x;i=j+1)
	{
		j=x/(x/i);
		s+=(x/i)*(j-i+1);
	}
	return s;
}
int b[1000010];
int pri[1000010];
int cnt;
int miu[1000010];
int main()
{
	ll i,j;
	miu[1]=1;
	for(i=2;i<=1000000;i++)
	{
		if(!b[i])
		{
			pri[++cnt]=i;
			miu[i]=-1;
		}
		for(j=1;j<=cnt&&i*pri[j]<=1000000;j++)
		{
			b[i*pri[j]]=1;
			if(i%pri[j]==0)
			{
				miu[i*pri[j]]=0;
				break;
			}
			miu[i*pri[j]]=-miu[i];
		}
	}
	ll ans=0;
	ll n;
	scanf("%lld",&n);
	for(i=1;i*i<=n;i++)
		ans=(ans+miu[i]*gao(n/(i*i)))%p;
	ans=(ans+p)%p;
	printf("%lld\n",ans);
	return 0;
}
posted @ 2018-03-06 11:41  ywwyww  阅读(260)  评论(0)    收藏  举报