P3455 [POI2007]ZAP-Queries(莫比乌斯反演)

35 篇文章 0 订阅

题目传送门

前置: 对于函数 f ( x ) f(x) f(x) F ( x ) F(x) F(x)

如果有 F ( n ) = ∑ d ∣ n f ( d ) F(n)=\sum\limits_{d|n}f( d ) F(n)=dnf(d),那么有 f ( n ) = ∑ d ∣ n μ ( d ) F ( n d ) f(n)=\sum\limits_{d|n} \mu(d)F(\cfrac nd) f(n)=dnμ(d)F(dn)
如果有 F ( n ) = ∑ n ∣ d f ( d ) F(n)=\sum\limits_{n|d}f(d) F(n)=ndf(d),那么有 f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) f(n)=\sum\limits_{n|d} \mu(\cfrac dn)F(d) f(n)=ndμ(nd)F(d)

题意: T T T组询问,给你 a , b , d a,b,d a,b,d,求出 1 ≤ x ≤ a , 1 ≤ y ≤ b , g c d ( x , y ) = d 1\le x \le a,1 \le y \le b,gcd(x,y)=d 1xa,1yb,gcd(x,y)=d 的数量。

思路: 以下推导中,除法均为整数。

f ( d ) = ∑ x = 1 a ∑ y = 1 b [ g c d ( x , y ) = d ] f(d) = \sum\limits_{x=1}^a \sum\limits_{y=1}^b [gcd(x,y)=d] f(d)=x=1ay=1b[gcd(x,y)=d]
F ( n ) = ∑ n ∣ k f ( k ) = ∑ n ∣ k ∑ x = 1 a ∑ y = 1 b [ g c d ( x , y ) = k ] = ∑ x = 1 a ∑ y = 1 b [ n ∣ g c d ( x , y ) ] = ∑ x = 1 a [ n ∣ x ] ∑ y = 1 b [ n ∣ y ] = a n ∗ b n \begin{aligned} F(n) &=\sum\limits_{n|k}f(k)\\ &=\sum\limits_{n|k}\sum\limits_{x=1}^a \sum\limits_{y=1}^b [gcd(x,y)=k]\\ &=\sum\limits_{x=1}^a \sum\limits_{y=1}^b [n|gcd(x,y)]\\ &=\sum\limits_{x=1}^a[n|x]\sum\limits_{y=1}^b[n|y]\\ &=\cfrac{a}{n}*\cfrac{b}{n}\\ \end{aligned} F(n)=nkf(k)=nkx=1ay=1b[gcd(x,y)=k]=x=1ay=1b[ngcd(x,y)]=x=1a[nx]y=1b[ny]=nanb

由于有第一步的 F ( n ) = ∑ n ∣ k f ( k ) F(n) =\sum\limits_{n|k}f(k) F(n)=nkf(k) ,所以有 f ( d ) = ∑ d ∣ k μ ( k d ) F ( k ) f(d)=\sum\limits_{d|k}\mu(\cfrac{k}{d})F(k) f(d)=dkμ(dk)F(k)

f ( d ) = ∑ d ∣ k μ ( k d ) F ( k ) = ∑ d ∣ k μ ( k d ) ∗ a k ∗ b k \begin{aligned} f(d)&=\sum\limits_{d|k}\mu(\cfrac{k}{d})F(k)\\ &=\sum\limits_{d|k}\mu(\cfrac{k}{d})*\cfrac{a}{k}*\cfrac{b}{k}\end{aligned} f(d)=dkμ(dk)F(k)=dkμ(dk)kakb

t = k d t=\cfrac kd t=dk

f ( d ) = ∑ t = 1 μ ( t ) a t ∗ d ∗ b t ∗ d = ∑ t = 1 μ ( t ) a d t ∗ b d t \begin{aligned} f(d)&=\sum\limits_{t=1}\mu(t)\cfrac{a}{t*d}*\cfrac{b}{t*d}\\ &=\sum\limits_{t=1}\mu(t)\cfrac{\cfrac ad}{t}*\cfrac{\cfrac bd}{t} \end{aligned} f(d)=t=1μ(t)tdatdb=t=1μ(t)tdatdb

莫比乌斯函数用欧拉筛筛出来,做一下前缀和,接下来就可以用除法分块计算答案了,时间复杂度为 O ( T n ) O(T\sqrt n) O(Tn )

代码:

bool ok[N];
int p[N],mu[N];
void euler()
{
	mu[1] = 1;
	for(int i=2; i<N; i++)
	{
		if(!ok[i])
		{
			p[++p[0]] = i;
			mu[i] = -1;
		}
		for(int j=1; j<=p[0]&&p[j]*i<N; j++)
		{
			ok[p[j]*i] = 1;
			if(i%p[j]==0)
				mu[i*p[j]] = 0;
			else mu[i*p[j]] = -mu[i];
		}
	}
	for(int i=2; i<N; i++)
		mu[i] += mu[i-1];
}


signed main()
{
	int t;
	cin>>t;
	euler();
	while(t--)
	{
		int a,b,d;
		cin>>a>>b>>d;
		a/=d;
		b/=d;
		int mi = min(a,b);
		int res = 0;
		for(int i=1,j; i<=mi; i=j+1)
		{
			j = min(a/(a/i),b/(b/i));
			res += (a/i) * (b/i) * (mu[j]-mu[i-1]);
		}
		cout<<res<<endl;
	}



	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值