BZOJ1101: [POI2007]Zap【数论分块+莫比乌斯函数】

本文介绍了解决POI2007[Zap]问题的方法,该问题涉及到数论中的莫比乌斯函数及数论分块技巧。通过将原始问题转化为更简单的形式,并利用莫比乌斯函数的性质,最终实现了一个高效的求解算法。

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

1101: [POI2007]Zap

原式为 ∑ i = 1 A ∑ j = 1 B [ ( i , j ) = = D ] \large \sum_{i=1}^{A} \sum_{j=1}^{B} [(i,j)==D] i=1Aj=1B[(i,j)==D]

基本操作,除掉D

∑ i = 1 A D ∑ j = 1 B D [ ( i , j ) = = 1 ] \large \sum_{i=1}^{\frac{A}{D}} \sum_{j=1}^{\frac{B}{D}} [(i,j)==1] i=1DAj=1DB[(i,j)==1]

已知 ∑ d ∣ n μ ( d ) = [ n = = 1 ] \large \sum_{d|n} \mu(d)=[n==1] dnμ(d)=[n==1]

所以 ∑ i = 1 A D ∑ j = 1 B D ∑ d ∣ ( i , j ) μ ( d ) \large \sum_{i=1}^{\frac{A}{D}} \sum_{j=1}^{\frac{B}{D}} \sum_{d|(i,j)} \mu(d) i=1DAj=1DBd(i,j)μ(d)

移项 ∑ d = 1 m i n ( A D , B D ) μ ( d ) ∑ d ∣ i ∑ d ∣ j 1 \large \sum_{d=1}^{min(\frac{A}{D},\frac{B}{D})} \mu(d) \sum_{d|i} \sum_{d|j} 1 d=1min(DA,DB)μ(d)didj1

等于 ∑ d = 1 m i n ( A D , B D ) μ ( d ) [ A D i ] [ B D j ] \large \sum_{d=1}^{min(\frac{A}{D},\frac{B}{D})} \mu(d) [\frac{A}{Di}][\frac{B}{Dj}] d=1min(DA,DB)μ(d)[DiA][DjB]

数论分块就可以了。

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=50005;
int T,A,B,D,cnt,p[MAXN],mu[MAXN];long long Ans;
bool vis[MAXN];
void make_p(){
	vis[0]=vis[1]=1;mu[1]=1;
	for(int i=2;i<=50000;i++){
		if(!vis[i]) p[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&i*p[j]<=50000;j++){
			int x=i*p[j];vis[x]=1;
			if(i%p[j]==0){mu[x]=0;break;}
			else mu[x]=-mu[i];
		}
	}
	for(int i=2;i<=50000;i++) mu[i]+=mu[i-1];
}
int main(){
	make_p();
	scanf("%d",&T);
	while(T--){
		scanf("%d%d%d",&A,&B,&D);Ans=0;A/=D,B/=D;
		for(int i=1,fi;i<=min(A,B);i=fi+1){
			fi=min((A/(A/i)),B/(B/i));fi=min(fi,min(A,B));
			Ans+=1ll*(mu[fi]-mu[i-1])*(A/i)*(B/i);
		}
		printf("%lld\n",Ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值