Codeforces Round #725 (Div. 3)
比赛链接
Codeforces Round #725 (Div. 3)
D. Another Problem About Dividing Numbers
给定两个整数 \(a, b\) 和一个操作数 \(k\) 。对于每一次操作,你有如下两种选择:
- 选择一个能整除 \(a\) 的大于一的整数 \(c\) ,用 \(\frac{a} { c }\) 替换a 。
- 选择一个能整除 \(b\) 的大于一的整数 \(c\) ,用 \(\frac{b}{c}\) 替换 \(b\) 。
然后询问,是否存在一种操作方法,使得在恰好 \(k\) 次操作后, \(a=b\) 。
数据范围: \(1<a, b, k<10^{9}\) 。
解题思路
质因数分解
先求出 \(a\) 和 \(b\) 的质因子总数 \(s\),\(k>s\) 显然是不合要求的,而 \(k\leq s\) 时需要分情况考虑,先特判 \(k=1\) 的情况,而如果 \(k=2\),且仍有 \(k\leq s\) 的情况,则可使 \(a=b=1\) 满足条件,可以发现:只要 \(k\leq s\),最后一定可以使 \(a=b=1\),所以关键在于求出质因子个数,但每次直接分解需要 \(O(\sqrt{10^9})\) 的复杂度,太高,可以考虑先线性筛出 \(1\sim \sqrt{10^9}\) 内的质数,这样的数有 \(3401\) 个,再拿这些质数分解,同时可以记忆化数的质因数个数
- 时间复杂度:\(O(3401\times t)\)
代码
// Problem: D. Another Problem About Dividing Numbers
// Contest: Codeforces - Codeforces Round #725 (Div. 3)
// URL: https://codeforces.com/contest/1538/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=1e5+5;
int prime[N],v[N],m,t,a,b,k;
unordered_map<int,int> f;
void primes(int n)
{
for(int i=2;i<=n;i++)
{
if(v[i]==0)
{
prime[++m]=i;
v[i]=i;
}
for(int j=1;j<=m;j++)
{
if(i*prime[j]>=N||v[i]<prime[j])break;
v[i*prime[j]]=prime[j];
}
}
}
int main()
{
help;
primes(sqrt(1e9));
for(cin>>t;t;t--)
{
cin>>a>>b>>k;
if(k==1)
{
if(a<b)swap(a,b);
puts(a%b==0&&a/b>1?"YES":"NO");
continue;
}
int res=0,ta=a,tb=b,cnta=f[a],cntb=f[b];
if(cnta==0)
{
for(int i=1;i<=m&&prime[i]<=a;i++)
while(a%prime[i]==0)
{
cnta++,a/=prime[i];
if(f[a])
{
cnta+=f[a];
a=0;
break;
}
}
if(a>1)cnta++;
}
f[ta]=cnta;
if(cntb==0)
{
for(int i=1;i<=m&&prime[i]<=b;i++)
while(b%prime[i]==0)
{
cntb++,b/=prime[i];
if(f[b])
{
cntb+=f[b];
b=0;
break;
}
}
if(b>1)cntb++;
}
f[tb]=cntb;
puts(f[ta]+f[tb]>=k?"YES":"NO");
}
return 0;
}