【XSY2719】prime 莫比乌斯反演

题目描述

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

  (nleq{10}^{12})

题解

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

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

[egin{align} s&=sum_{i=1}^nsum_{d|i}[gcd(d,frac{i}{d})=1]\ &=sum_{i=1}^nsum_{d|i}sum_{j|d ext{&&}j|frac{i}{d}}mu(j)\ &=sum_{i=1}^nsum_{j^2|i}g(frac{i}{j^2})mu(j)\ &=sum_{j=1}^sqrt{n}mu(j)sum_{i=1}^{lfloorfrac{n}{j^2} floor}g(i)\ &=sum_{j=1}^sqrt{n}mu(j)sum_{i=1}^{lfloorfrac{n}{j^2} floor}lfloorfrac{n}{j^2i} floor end{align} ]

  时间复杂度:(O(sqrt nlog 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
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/ywwyww/p/8513531.html