Codeforces 1499 D - The Number of Pairs (数学 + 整数条件推关系)

这篇博客探讨了如何通过数学转换和编程解决一个涉及最大公约数(gcd)和最小公倍数(lcm)的问题。作者提供了两种思路,将原始等式转化为关于gcd和lcm的关系,并利用裴蜀定理来确定解的存在性。通过预处理素因子个数,避免了在线计算导致的时间超限错误,最终实现了计算满足条件的二元组数量。
摘要由CSDN通过智能技术生成

在这里插入图片描述
题意:
给定你 c , d , x c,d,x c,d,x三个数然问你存在多少对二元组 ( a , b ) (a,b) (a,b)使得等式 c ∗ l c m ( a , b ) − d ∗ g c d ( a , b ) = x c * lcm(a,b) - d * gcd(a,b) = x clcm(a,b)dgcd(a,b)=x恒成立, ( a , b ) (a,b) (a,b) ( b , a ) (b,a) (b,a)算作两个不同的二元组。
纯抄袭大佬思路

思路一:
先把给定的式子转化一下, c ∗ l c m ( a , b ) = d ∗ g c d ( a , b ) + x c * lcm(a,b) = d * gcd(a,b) + x clcm(a,b)=dgcd(a,b)+x,两边同除 g c d ( a , b ) gcd(a,b) gcd(a,b),得 l c m ( a , b ) g c d ( a , b ) = x g c d ( a , b ) + d c \frac{lcm(a,b)}{gcd(a,b)} = \frac{\frac{x}{gcd(a,b)} + d}{c} gcd(a,b)lcm(a,b)=cgcd(a,b)x+d,因为左边肯定是整数,所以这就决定了 g c d ( a , b ) gcd(a,b) gcd(a,b)必须是 x x x的因子。

l c m ( a , b ) g c d ( a , b ) \frac{lcm(a,b)}{gcd(a,b)} gcd(a,b)lcm(a,b)就是 a a a b b b中不相同的素因子这里不相等是指两边把相同幂次的素因子约去之后剩余的部分,可知这一部分的因子一定是一部分属于 a a a,一部分属于 b b b,二者是不相交的,所以本质就相当于我从 n n n种素因子中挑出两堆分给 a a a b b b,但是还有 1 1 1和这个数本身也是可以组合的,所以就是 ( n 0 ) \tbinom{n}{0} (0n) + ( n 1 ) \tbinom{n}{1} (1n) + . . . . .... .... + ( n n ) \tbinom{n}{n} (nn) = 2 n 2^n 2n,其中 n n n代表素因子个数。

特别地,挑0,那么另一边就是本身那个数,挑n,那么另一边就是0。

思路二:
另一种思路, c ∗ a ∗ b g c d ( a , b ) = x + d ∗ g c d ( a , b ) c * \frac{a*b}{gcd(a,b)} = x + d * gcd(a,b) cgcd(a,b)ab=x+dgcd(a,b),两侧同除 g c d ( a , b ) gcd(a,b) gcd(a,b) a ∗ b g c d ( a , b ) ∗ g c d ( a , b ) = x g c d ( a , b ) + d c \frac{a*b}{gcd(a,b)*gcd(a,b)} = \frac{\frac{x}{gcd(a,b)} + d}{c} gcd(a,b)gcd(a,b)ab=cgcd(a,b)x+d,设 A = a g c d ( a , b , B = b g c d ( a , b ) A = \frac{a}{gcd(a,b},B = \frac{b}{gcd(a,b)} A=gcd(a,ba,B=gcd(a,b)b,可知 A A A B B B互质,故其实就变为找到两个互质的数使它们相乘等于右侧,而右侧等式又可知 g c d ( a , b ) gcd(a,b) gcd(a,b)定为 x x x的因子,所以我们枚举 x x x的因子,然后找右侧这个数的素因子即可,再分配成两个部分相乘,同理也是 2 n 2^n 2n的数量。

其实 g c d ( a , b ) ∣ x gcd(a,b)|x gcd(a,b)x这个条件也可以有裴蜀定理的推论得到,若 a x + b y = z ax +by = z ax+by=z,对于整数 x x x y y y来说有解,那么 g c d ( a , b ) ∣ z gcd(a,b) | z gcd(a,b)z,而题目里的 g c d ( l c m ( a , b ) , g c d ( a , b ) ) = g c d ( a , b ) gcd(lcm(a,b),gcd(a,b)) = gcd(a,b) gcd(lcm(a,b),gcd(a,b))=gcd(a,b)

需要注意的是,要预处理出每个数的素因子个数,每个数现算的话,会TLE,还有当对于数学式存在分式的同时,给出整数这个条件,可能就是突破口。

#include <bits/stdc++.h>

using namespace std;

#define pb emplace_back
#define MP make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define lson rt<<1
#define rson rt<<1|1
#define CLOSE std::ios::sync_with_stdio(false)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-6;
const int N = 2e7;
bool is_prime[N + 10];
int Fac[N + 10],prime[N],cnt;

void Prime() {
	for(int i = 2;i <= N;i ++) is_prime[i] = true;
	for(int i = 2;i <= N;i ++) {
		if(is_prime[i]) {
			prime[++cnt] = i;
			Fac[i] = 1;
		}
		for(int j = 1;j <= cnt && prime[j] * i <= N;j ++) {
			is_prime[prime[j]*i] = false;
			if(i % prime[j] == 0) {
				Fac[prime[j]*i] = Fac[i];//这里其实i的素因子是包含prime[j]的,所以prime[j]是不能放进去的
				break;
			}
			Fac[prime[j]*i] = Fac[i] + 1;
		}
	}
}

int d,c,x;
ll cal(int x) {
	int tmp = d + x;
	if(tmp % c == 0) {
		tmp = tmp / c;
		return 1LL << Fac[tmp];
	} 
	return 0;
}

int main() {
	Prime();
	int T;scanf("%d",&T);
	while(T--) {
		scanf("%d%d%d",&c,&d,&x);
		ll ans = 0;
		for(int i = 1;i * i <= x;i ++) {
			if(x % i == 0) {
				ans += cal(x/i);
				if(x / i != i)
					ans += cal(i);
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值