Comet OJ - Contest #8 E神奇函数(莫比乌斯函数容斥)

本文解析了一道涉及神奇函数f(x)的数学竞赛题,该函数值与x的最大平方因子有关。通过容斥原理和莫比乌斯函数的应用,详细推导了求解f函数前缀和的算法,最终简化为欧拉函数的计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Comet OJ - Contest #8 E神奇函数(莫比乌斯函数容斥)

题目大意

定义 d ( x ) d(x) d(x)的值为x的最小素因子,定义
f ( x ) = { 1 x = 1 d ( x ) f ( x d 2 ( x ) ) x > 1 , d 2 ( x ) ∣ x d ( x ) f ( x d ( x ) ) o t h e r f(x)= \begin{cases} 1&x=1\\ d(x)f(\frac{x}{d^2(x)}) &x>1,d^2(x)|x\\ d(x)f(\frac{x}{d(x)})&other \end{cases} f(x)=1d(x)f(d2(x)x)d(x)f(d(x)x)x=1x>1,d2(x)xother
求f函数前缀和

https://cometoj.com/contest/58/problem/E?problem_id=2759

解题思路

f函数的值实际上就是x的最大平方因子开根号为此我们枚举原式
∑ i = 1 n i ⋅ g ( ⌊ n i 2 ⌋ ) \sum_{i=1}^{\sqrt{n}}i\cdot g(\left\lfloor\frac{n}{i^2}\right\rfloor) i=1n ig(i2n)
其中 g ( x ) g(x) g(x)的定义是小于等于x的,无完全平方因子的数的数量。这就是一个非常经典的容斥原理的题目了。即枚举无素数平方因子,至少有一个素数平方因子,至少有两个素数平方因子,…对此进行容斥,发现容斥的系数恰好枚举的数的莫比乌斯函数的值,则有
g ( x ) = ∑ i = 1 x μ ( i ) ⋅ ⌊ n i 2 ⌋ g(x)=\sum_{i=1}^{\sqrt x}\mu(i)\cdot\left\lfloor\frac{n}{i^2}\right\rfloor g(x)=i=1x μ(i)i2n
故原式等于
∑ i = 1 n i ⋅ ∑ j = 1 ⌊ n i 2 ⌋ μ ( j ) ⌊ n i 2 j 2 ⌋ \sum_{i=1}^{\sqrt n}i\cdot\sum_{j=1}^{\sqrt{\left\lfloor\frac{n}{i^2}\right\rfloor}}\mu(j)\left\lfloor\frac{n}{i^2j^2}\right\rfloor i=1n ij=1i2n μ(j)i2j2n
k = i ⋅ j k=i\cdot j k=ij,将原式改变为枚举k,则有
∑ k = 1 n ⌊ n k 2 ⌋ ∑ i ∣ k i ⋅ μ ( k i ) \sum_{k=1}^{\sqrt n}\left\lfloor\frac{n}{k^2}\right\rfloor\sum_{i|k}i\cdot\mu(\frac{k}{i}) k=1n k2nikiμ(ik)
可以发现后面那个式子就是单位函数卷积莫比乌斯函数,根据公式已知其值为欧拉函数,故原式可以写作
∑ k = 1 n ⌊ n k 2 ⌋ φ ( k ) \sum_{k=1}^{\sqrt n}\left\lfloor\frac{n}{k^2}\right\rfloor\varphi(k) k=1n k2nφ(k)

AC代码

#include<bits/stdc++.h>
using namespace std;
#define int long long 
typedef long long LL;
LL n;
const int size=1e7+5;
bool prime[size];int p[size];
int phi[size];
int tot=0;
void init()
{
	phi[1]=1;
	for(int i=1;i<size;i++) prime[i]=true;
	for(int i=2;i<size;i++)
	{
		if(prime[i])
		{
		 	p[++tot]=i;
		 	phi[i]=i-1;
		}
		for(int j=1;j<=tot&&p[j]*i<size;j++)
		{
			prime[i*p[j]]=false;
			if(i%p[j]==0)
			{
				phi[i*p[j]]=phi[i]*p[j];
				break;
			}
			else phi[i*p[j]]=phi[i]*phi[p[j]];
		}
	}
}	 
int32_t main()
{
	int t;
	//freopen("a.in","r",stdin);
	init();
	scanf("%lld",&t);
	while(t--)
	{
		scanf("%lld",&n);
		int s=sqrt(n);
		LL ans=0;
		for(int i=1;i<=s;i++)
		{
			ans+=n/(i*i)*phi[i];
		}
		printf("%lld\n",ans);
	}
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值