【XSY2719】prime(积性函数,莫比乌斯反演)

题意:求 ( ∑ i = 1 n 2 f ( i ) )   m o d   998244353 \left(\sum\limits_{i=1}^n2^{f(i)}\right)\bmod 998244353 (i=1n2f(i))mod998244353,其中 f ( i ) f(i) f(i) 表示 i i i 的不同质因子的个数, n ≤ 1 0 12 n\leq 10^{12} n1012


一开始发现 g ( x ) = 2 f ( x ) g(x)=2^{f(x)} g(x)=2f(x) 是积性函数以为能直接 min_25 筛(

结果时间爆炸(

考虑 2 f ( i ) 2^{f(i)} 2f(i) 的组合意义,得到 2 f ( i ) = ∑ j ∣ i μ 2 ( j ) 2^{f(i)}=\sum\limits_{j|i}\mu^2(j) 2f(i)=jiμ2(j)

于是:
∑ i = 1 n 2 f ( i ) = ∑ i = 1 n ∑ j ∣ i μ 2 ( j ) = ∑ i = 1 n ⌊ n i ⌋ μ 2 ( i ) \begin{aligned} &\sum_{i=1}^n2^{f(i)}\\ =&\sum_{i=1}^n\sum_{j|i}\mu^2(j)\\ =&\sum_{i=1}^n\lfloor\dfrac{n}{i}\rfloor\mu^2(i) \end{aligned} ==i=1n2f(i)i=1njiμ2(j)i=1ninμ2(i)
如果我们能快速求出 μ 2 ( i ) \mu^2(i) μ2(i) n n n 的基本和组上的前缀和,就能整除分块了。

注意到设 d d d x x x 的最大平方因子(如 x = 3 x=3 x=3 d = 1 d=1 d=1 x = 24 x=24 x=24 d = 2 d=2 d=2),那么:
μ 2 ( x ) = [ d = 1 ] = ∑ i ∣ d μ ( i ) \mu^2(x)=[d=1]=\sum_{i|d}\mu(i) μ2(x)=[d=1]=idμ(i)
根据 d d d 的定义, x x x 可以写成 y × d 2 y\times d^2 y×d2 的形式,其中 y y y 没有平方因子。

那么枚举 i ∣ d i|d id 相当于枚举 i 2 ∣ x i^2|x i2x,于是 μ 2 ( x ) = ∑ i 2 ∣ x μ ( i ) \mu^2(x)=\sum\limits_{i^2|x}\mu(i) μ2(x)=i2xμ(i)

于是原式为:
= ∑ i = 1 n ⌊ n i ⌋ ∑ d 2 ∣ i μ ( d ) = ∑ d = 1 n μ ( d ) ∑ j = 1 n / ( d 2 ) ⌊ n d 2 j ⌋ \begin{aligned} =&\sum_{i=1}^n\lfloor\dfrac{n}{i}\rfloor \sum_{d^2|i}\mu(d)\\ =&\sum_{d=1}^{\sqrt n}\mu(d)\sum_{j=1}^{n/(d^2)}\lfloor\dfrac{n}{d^2j}\rfloor \end{aligned} ==i=1nind2iμ(d)d=1n μ(d)j=1n/(d2)d2jn
g ( n ) = ∑ i = 1 n ⌊ n i ⌋ g(n)=\sum\limits_{i=1}^n\lfloor\dfrac{n}{i}\rfloor g(n)=i=1nin,于是原式为:
= ∑ d = 1 n μ ( d ) g ( ⌊ n d 2 ⌋ ) =\sum_{d=1}^{\sqrt n}\mu(d)g\left(\lfloor\dfrac{n}{d^2}\rfloor\right) =d=1n μ(d)g(d2n)
我们暴力枚举每一个 d d d,并每次暴力整除分块求出 g g g 即可。

时间复杂度:
∑ i = 1 n O ( n i 2 ) = ∑ i = 1 n O ( n i ) = O ( n ln ⁡ n ) \sum _{i=1}^{\sqrt n}O\left(\sqrt{\dfrac{n}{i^2}}\right)=\sum_{i=1}^{\sqrt n}O\left(\dfrac{\sqrt n}{i}\right)=O\left(\sqrt n\ln \sqrt n\right) i=1n O(i2n )=i=1n O(in )=O(n lnn )

代码如下:

#include<bits/stdc++.h>

#define N 1000010
#define ll long long

using namespace std;

namespace modular
{
	const int mod=998244353;
	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
	inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
	inline int mul(int x,int y){return 1ll*x*y%mod;}
}using namespace modular;

ll n;
int sn;
int cnt,prime[N],mu[N];
bool notprime[N];

void init()
{
	mu[1]=1;
	for(int i=2;i<=sn;i++)
	{
		if(!notprime[i])
		{
			prime[++cnt]=i;
			mu[i]=mod-1;
		}
		for(int j=1,x;j<=cnt&&(x=i*prime[j])<=sn;j++)
		{
			notprime[x]=1;
			if(!(i%prime[j])) break;
			mu[x]=mul(mu[i],mu[prime[j]]);
		}
	}
}

int g(ll n)
{
	int ans=0;
	for(ll l=1,r;l<=n;l=r+1)
	{
		r=n/(n/l);
		ans=add(ans,mul((r-l+1)%mod,(n/l)%mod));
	}
	return ans;
}

int main()
{
	scanf("%lld",&n);
	sn=sqrt(n);
	init();
	int ans=0;
	for(int d=1;d<=sn;d++)
		ans=add(ans,mul(mu[d],g(n/d/d)));
	printf("%d\n",ans);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值