「NOIP 2009」Hankson 的趣味题

传送门


problem

给定 a 0 , a 1 , b 0 , b 1 a_0,a_1,b_0,b_1 a0,a1,b0,b1,求满足下列条件的 x x x 的数量:

  • gcd ⁡ ( x , a 0 ) = a 1 \gcd(x,a_0)=a_1 gcd(x,a0)=a1
  • l c m ( x , b 0 ) = b 1 \mathrm{lcm}(x,b_0)=b_1 lcm(x,b0)=b1

数据范围: 1 ≤ a 0 , a 1 , b 0 , b 1 ≤ 2 × 1 0 9 1\le a_0,a_1,b_0,b_1\le2\times 10^9 1a0,a1,b0,b12×109 T ≤ 2000 T\le2000 T2000,其中 T T T 是数据组数。


solution

这道题不难,主要就是 gcd ⁡ \gcd gcd 的一个小性质: gcd ⁡ ( x , y ) = k ⟹ gcd ⁡ ( x k , y k ) = 1 \gcd(x,y)=k\Longrightarrow \gcd(\frac x k,\frac y k)=1 gcd(x,y)=kgcd(kx,ky)=1

那么第一个式子就是 gcd ⁡ ( x a 1 , a 0 a 1 ) = 1 \gcd(\frac x{a_1},\frac{a_0}{a_1})=1 gcd(a1x,a1a0)=1

第二个式子,稍微化简一下可得:

x b 0 gcd ⁡ ( x , b 0 ) = b 1 gcd ⁡ ( x , b 0 ) = x b 0 b 1 gcd ⁡ ( b 1 b 0 , b 1 x ) = 1 \begin{aligned} \frac{xb_0}{\gcd(x,b_0)}&=b_1\\ \gcd(x,b_0)&=\frac{xb_0}{b_1}\\ \gcd(\frac{b_1}{b_0},\frac{b_1}{x})&=1 \end{aligned} gcd(x,b0)xb0gcd(x,b0)gcd(b0b1,xb1)=b1=b1xb0=1

由于 x x x b 1 b_1 b1 的因数,我们就可以 O ( b 1 ) O(\sqrt{b_1}) O(b1 ) 枚举因数来解决了。

时间复杂度 O ( T b 1 ) O(T\sqrt{b_1}) O(Tb1 )


code

#include<bits/stdc++.h>
using namespace std;
int T,a0,a1,b0,b1;
bool check(int x){
	if(x%a1)  return false;
	if(__gcd(b1/b0,b1/x)!=1)  return false;
	if(__gcd(x/a1,a0/a1)!=1)  return false;
	return true;
}
int main(){
	scanf("%d",&T);
	while(T--){
		int ans=0;
		scanf("%d%d%d%d",&a0,&a1,&b0,&b1);
		for(int i=1;i*i<=b1;++i){
			if(b1%i==0){
				ans+=check(i);
				if(i*i!=b1)  ans+=check(b1/i);
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值