【POI 2007】ZAP-Queries

本文介绍了一种解决计数问题的方法,利用莫比乌斯反演求解特定数学条件下的整数对数量。通过分析给定参数a、b、d下满足特定gcd条件的整数对(x,y),并提供了解决方案和代码实现。

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

【题目】

传送门

Description

Byteasar the Cryptographer works on breaking the code of BSA (Byteotian Security Agency). He has alreadyfound out that whilst deciphering a message he will have to answer multiple queries of the form"for givenintegers aa, bb and dd, find the number of integer pairs ( x , y ) (x,y) (x,y) satisfying the following conditions:

1 ≤ x ≤ a 1\le x\le a 1xa, 1 ≤ y ≤ b 1\le y\le b 1yb, g c d ( x , y ) = d gcd(x,y)=d gcd(x,y)=d, where g c d ( x , y ) gcd(x,y) gcd(x,y) is the greatest common divisor of x x x and y y y".

Byteasar would like to automate his work, so he has asked for your help.

TaskWrite a programme which:

reads from the standard input a list of queries, which the Byteasar has to give answer to, calculates answers to the queries, writes the outcome to the standard output.

Input

The first line of the standard input contains one integer n n n ( 1 ≤ n ≤ 50000 1\le n\le 50000 1n50000),denoting the number of queries.

The following nn lines contain three integers each: a a a, b b b and d d d( 1 ≤ d ≤ a , b ≤ 50000 1\le d\le a,b\le 50000 1da,b50000), separated by single spaces.

Each triplet denotes a single query.

Output

Your programme should write nn lines to the standard output. The i’th line should contain a single integer: theanswer to the i’th query from the standard input.

Sample Input

2
4 5 2
6 4 3

Sample Output

3
2


【分析】

题目大意:有 n n n 组询问,每次给出 a , b , d a,b,d a,b,d,求出有多少对 ( x , y ) (x,y) (x,y) 满足 1 ≤ x ≤ a 1\le x\le a 1xa 1 ≤ y ≤ b 1\le y\le b 1yb gcd ⁡ ( x , y ) = d \gcd(x,y)=d gcd(x,y)=d

题目中实际上就是要我们求出 ∑ i = 1 a ∑ j = 1 b [    gcd ⁡ ( i , j ) = d    ] \sum_{i=1}^a\sum_{j=1}^b[\;\gcd(i,j)=d\;] i=1aj=1b[gcd(i,j)=d]把它化个简就是 ∑ i = 1 ⌊ a d ⌋ ∑ j = 1 ⌊ b d ⌋ [    gcd ⁡ ( i , j ) = 1    ] \sum_{i=1}^{\lfloor\frac{a}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{b}{d}\rfloor}[\;\gcd(i,j)=1\;] i=1daj=1db[gcd(i,j)=1]

我们定义(以下式子中 a ′ a' a 代表 ⌊ a d ⌋ \lfloor\frac{a}{d}\rfloor da b ′ b' b 代表 ⌊ b d ⌋ \lfloor\frac{b}{d}\rfloor db
f ( n ) = ∑ i = 1 a ′ ∑ j = 1 b ′ [    gcd ⁡ ( i , j ) = n    ] f(n)=\sum_{i=1}^{a'}\sum_{j=1}^{b'}[\;\gcd(i,j)=n\;] f(n)=i=1aj=1b[gcd(i,j)=n] F ( n ) = ∑ n ∣ k m i n ( a ′ , b ′ ) f ( k ) F(n)=\sum_{n|k}^{min(a',b')}f(k) F(n)=nkmin(a,b)f(k)

不难发现的是
F ( n ) = ⌊ a ′ n ⌋ ⌊ b ′ n ⌋ F(n)=\lfloor \frac{a'}{n}\rfloor\lfloor \frac{b '}{n}\rfloor F(n)=nanb

那么用莫比乌斯反演得到

f ( n ) = ∑ n ∣ k m i n ( a ′ , b ′ ) F ( k ) μ ( k n ) = ∑ n ∣ k m i n ( a ′ , b ′ ) μ ( k n ) ⌊ a ′ k ⌋ ⌊ b ′ k ⌋ f(n)=\sum_{n|k}^{min(a',b')}F(k)\mu(\frac{k}{n})=\sum_{n|k}^{min(a',b')}\mu(\frac{k}{n})\lfloor \frac{a'}{k}\rfloor\lfloor \frac{b '}{k}\rfloor f(n)=nkmin(a,b)F(k)μ(nk)=nkmin(a,b)μ(nk)kakb

根据 f ( n ) f(n) f(n) 的定义不难发现答案就是 f ( 1 ) f(1) f(1),也就是

f ( 1 ) = ∑ k = 1 m i n ( a ′ , b ′ ) μ ( k ) ⌊ a ′ k ⌋ ⌊ b ′ k ⌋ f(1)=\sum_{k=1}^{min(a',b')}\mu(k)\lfloor \frac{a'}{k}\rfloor\lfloor \frac{b '}{k}\rfloor f(1)=k=1min(a,b)μ(k)kakb

那么先统计出 μ \mu μ 函数的前缀和,再进行整除分块就可以解决这道题了。


【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 50005
#define Mod 998244353
using namespace std;
int prime[N],mu[N];
bool mark[N];
void linear_sieves()
{
	int i,j,sum=0;
	memset(mark,true,sizeof(mark));
	mark[0]=mark[1]=false,mu[1]=1;
	for(i=2;i<N;++i)
	{
		if(mark[i])  prime[++sum]=i,mu[i]=-1;
		for(j=1;j<=sum&&i*prime[j]<N;++j)
		{
			mark[i*prime[j]]=false;
			if(i%prime[j])  mu[i*prime[j]]=-mu[i];
			else  break;
		}
	}
	for(i=1;i<N;++i)  mu[i]+=mu[i-1];
}
int solve(int a,int b,int d)
{
	a/=d,b/=d;
	int i,j,ans=0;
	if(a>b)  swap(a,b);
	for(i=1;i<=a;i=j+1)
	{
		j=min(a/(a/i),b/(b/i));
		ans+=(mu[j]-mu[i-1])*(a/i)*(b/i);
	}
	return ans;
}
int main()
{
	int n,i,a,b,d;
	scanf("%d",&n);
	linear_sieves();
	for(i=1;i<=n;++i)
	{
		scanf("%d%d%d",&a,&b,&d);
		printf("%d\n",solve(a,b,d));
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值