省选专练之数学「LibreOJ β Round #4」求和(两种算法(容斥+莫比乌斯反演)/超级详细)

10 篇文章 0 订阅
10 篇文章 0 订阅

虽然考试的时候交了暴力(正解在手上却欧拉函数莫比乌斯函数傻傻分不清)

\sum_{i=1}^{N}\sum_{j=1}^{M}\mu ^{2}\left ( GCD(i,j) \right )= \sum_{i=1}^{N}\sum_{j=1}^{M}\sum_{k=1}^{min(N,M)}\mu ^{2}(k)\left [ GCD(i,j)==k \right ]

稍微交换一下枚举顺序

\sum_{i=1}^{\left \lfloor N/k \right \rfloor}\sum_{j=1}^{\left \lfloor M/k \right \rfloor}\sum_{k=1}\mu ^{2}\left ( k \right )\left [ GCD(i,j)==1 \right ]

使用莫比乌斯函数:\sum_{i=1}^{\left \lfloor N/k \right \rfloor}\sum_{j=1}^{\left \lfloor M/k \right \rfloor}\sum_{k=1}\mu ^{2}\left ( k \right )\sum_{t|(i,j)}\mu (t)

再次交换枚举顺序

\sum_{t=1}\mu (t)\sum_{k=1}\mu ^{2}\left ( k \right )\sum_{i=1}^{\left \lfloor N/kt \right \rfloor}\sum_{j=1}^{\left \lfloor M/kt \right \rfloor}

不妨令 x=dt 有

\sum_{t=1}\mu (\frac{x}{d})\sum_{k=1}\mu ^{2}\left ( k \right )\sum_{i=1}^{\left \lfloor N/x\right \rfloor}\sum_{j=1}^{\left \lfloor M/x \right \rfloor}

稍作转换:

\sum_{t=1}\mu (\frac{x}{d})\sum_{k|t}\mu ^{2}\left ( k \right )\sum_{i=1}^{\left \lfloor N/x\right \rfloor}\sum_{j=1}^{\left \lfloor M/x \right \rfloor}

再一次交换枚举顺序

\sum_{x}^{min(N,M)}\left \lfloor \frac{N}{x} \right \rfloor\left \lfloor \frac{M}{x} \right \rfloor\sum_{k|t}\mu (\frac{x}{k})\mu ^{2}\left ( k \right )

发现整数分块可以再一次On的预处理后得到O\left ( \sqrt{x} \right )的优秀时间复杂度

但是这是远远不够的

不妨设
F(x)=\sum_{k|t}\mu (\frac{x}{k})\mu ^{2}\left ( k \right )

打表找出规律:F(x)=\mu (\sqrt{x}) \sqrt{x}\epsilon \mathbb{N}

给出证明:

\sqrt{x}\notin \mathbb{N}\frac{x}{k}k会被枚举两次他们必然会两两抵消,或者就是0

所以存在O\left ( \sqrt{n} \right )的时间复杂度的预处理和O(\sqrt{n})的查询算法

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef int INT;
#define int long long
const int mod=998244353;
const int N=1e7+100;
int sum[N]={0},mu[N]={0},is_prime[N]={0},mark[N];
int cnt=0;
void pre_mul(){
	mu[1]=1;
	for(int i=2;i<N;i++){
		if(!mark[i]){
			cnt++;
			is_prime[cnt]=i;
			mu[i]=-1;
		}
		for(int j=1;j<=cnt&&is_prime[j]*i<N;j++){
			mark[is_prime[j]*i]=1;
			if(i%is_prime[j]==0){
				mu[is_prime[j]*i]=0;
				break;
			}
			mu[is_prime[j]*i]=-mu[i];
		}
	}
	sum[0]=0;
	for(int i=1;i<N;i++){
		sum[i]=mu[i]+sum[i-1];
	}
}
inline int Getsum(int x){
	int Id=sqrt(x);
	return sum[Id];
}
void Solve(){
	int n,m;
	cin>>n>>m;
	if(n>m)
		swap(n,m);
	int ans=0;
	int last;
	for(int i=1;i<=n;i=last+1){
		last=min(n/(n/i),m/(m/i));
		ans=(ans+((n/i)%mod)*((m/i)%mod)%mod*((Getsum(last)-Getsum(i-1))%mod)%mod+mod)%mod;
	}
	cout<<ans;
}
INT main(){
	pre_mul();
	Solve();
	return 0;
}

但是对于这一类题有一种更好的翻译:

\mu ^{2}\left ( x \right )\neq 0当且仅当\forall i*i不是x的约数

于是考虑容斥:

\sum_{t=1}^{min(\sqrt{x},\sqrt{y})}\mu \left ( t \right )\left \lfloor \frac{N}{t^{2}} \right \rfloor\left \lfloor \frac{M}{t^{2}} \right \rfloor就完了

而且整数分块有4的常数!!!

所以对一道题的翻译很重要啊。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef int INT;
#define int long long
const int mod=998244353;
const int N=4e6+100;
int sum[N]={0},mu[N]={0},is_prime[N]={0},mark[N];
int cnt=0;
void pre_mul(){
	mu[1]=1;
	for(int i=2;i<N;i++){
		if(!mark[i]){
			cnt++;
			is_prime[cnt]=i;
			mu[i]=-1;
		}
		for(int j=1;j<=cnt&&is_prime[j]*i<N;j++){
			mark[is_prime[j]*i]=1;
			if(i%is_prime[j]==0){
				mu[is_prime[j]*i]=0;
				break;
			}
			mu[is_prime[j]*i]=-mu[i];
		}
	}
	sum[0]=0;
	for(int i=1;i<N;i++){
		sum[i]=mu[i]+sum[i-1];
	}
}
inline int Getsum(int x){
	int Id=sqrt(x);
	return sum[Id];
}
void Solve(){
	int n,m;
	cin>>n>>m;
	if(n>m)
		swap(n,m);
	int ans=0;
	int last;
	for(int i=1;i;i++){
		int t=i*i;
		ans=ans+mu[i]*((n/t)%mod)%mod*((m/t)%mod)%mod;
		ans=(ans+mod)%mod;
		if(t>n)break;
	}
	cout<<ans<<'\n';
//	cout<<(((n%mod)*(m%mod)-ans)%mod+mod)%mod;
}
INT main(){
	pre_mul();
	Solve();
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值