CodeForces - 1538D Another Problem About Dividing Numbers(数学+构造)

该博客讨论了一种数学与编程相结合的问题,即如何通过质因子分解和特定操作使两个正整数相等。题目要求在限定的操作次数内,通过将数分解并去除不等于自身的因子,判断能否使两个数相等。当操作次数为1时,只有当两个数互为因数时才有解。通过质因子分解计算每个数的因子次数,如果总次数大于等于操作次数,则存在解决方案,否则无解。博客提供了具体的代码实现来解决这个问题。

题目链接:点击这里

题目大意:
给出两个正整数 a , b a,b a,b ,每轮可以选择二者之一,不妨令为 x x x ,用一个正整数 c ( c > 1 ) c(c>1) c(c>1) 来让其替换为 x c \frac x c cx
问经过 k k k 轮操作后是否能使 a , b a,b a,b 恰好相等

题目分析:
显然操作为给 x x x 去除掉他的一个不等于其本身的因子,最终都可以通过操作使其等于 1 1 1
先考虑一种特殊情况 k = 1 k=1 k=1 ,其特殊在只能对一个数进行操作,此时只有在 a ∣ b a|b ab b ∣ a b|a ba a ≠ b a\not=b a=b 时才会有解,其余情况均无解
不难想到此题跟质因子分解有关,令 x = p 1 k 1 ∗ p 2 k 2 ∗ . . . ∗ p t k t x=p_1^{k_1}*p_2^{k_2}*...*p_t^{k_t} x=p1k1p2k2...ptkt ,那么 x x x 至多可以分解 ∑ i = 1 t k i \sum_{i=1}^tk_i i=1tki 次,设 c n t 1 , c n t 2 cnt_1,cnt_2 cnt1,cnt2 分别为 a , b a,b a,b ∑ i = 1 t k i \sum_{i=1}^tk_i i=1tki,那么如果 c n t 1 + c n t 2 ≥ k cnt_1+cnt_2\ge k cnt1+cnt2k 显然我们可以通过操作使之都变为 1 1 1 ,其他情况就是无解情况

具体细节见代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
int read()
{
	int res = 0,flag = 1;
	char ch = getchar();
	while(ch<'0' || ch>'9')
	{
		if(ch == '-') flag = -1;
		ch = getchar();
	}
	while(ch>='0' && ch<='9')
	{
		res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
		ch = getchar();
	}
	return res*flag;
}
const int maxn = 2e5+5;
const int mod = 1e9+7;
const double pi = acos(-1);
const double eps = 1e-8;
int a,b,k,cnt,pri[maxn];
bool vis[maxn];
void get_pri(int n)
{
	vis[1] = true;
	for(int i = 2;i <= n;i++)
	{
		if(!vis[i]) pri[++cnt] = i;
		for(int j = 1;j <= cnt && i*pri[j] <= n;j++)
		{
			vis[i*pri[j]] = true;
			if(i%pri[j] == 0) break;
		}
	}
}
int div(int n)
{
	int res = 0;
	for(int i = 1;i<=cnt && pri[i]<=n;i++)
	{
		if(n%pri[i]) continue;
		while(n%pri[i] == 0)
		{
			n /= pri[i];
			res++;
		}
	}
	if(n != 1) res++;
	return res;
}
int main()
{
	int t = read();
	get_pri(maxn-1);
	while(t--)
	{
		a = read(),b = read(),k = read();
		if(k == 1)
		{
			if((a%b==0 || b%a==0) && a!=b) puts("YES");
			else puts("NO");
			continue;
		}
		if(div(a)+div(b) >= k) puts("YES");
		else puts("NO");
	} 
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值