1. 程式人生 > 其它 >CF1538D Another Problem About Dividing Numbers題解

CF1538D Another Problem About Dividing Numbers題解

CF1538D

題意

給你兩個數\(a \ b\),每個操作是從這兩個數中選擇一個,然後選一個可以整除你選的數的數(假設是\(c\)),然後你可以把你選的數(假設是\(a\))變成\(\frac{a}{c}\),問你能不能經過\(k\)次操作讓\(a\)\(b\)相等

分析

發現最大操作次數是把這兩個數都變成\(1\),而且每次都拿掉一個質因子,所以最大操作次數(設為\(Max\))就是把兩個數質因數分解之後的冪次和.而最小操作次數,如果這兩個數的質因子全都相同(也就是一個能整除另一個),那麼最小操作次數是\(1\),如果這兩個數相同,那麼最小操作次數(設為\(Min\))就是\(0\),其他的情況下,最小操作次數就是\(2\)

.我們發現,如果\(Min \leq k \leq Max\),那麼顯然它是可以的(可以想成拿質因子的時候多拿或者少拿使得需要的次數加減\(1\)),否則就不行.
所以只要質因數分解一下就可以了.發現如果一個\(10^9\)之內的數不是質數,那麼它的最大的質因子一定不會超過\(\sqrt{n}\),所以我們可以預處理把所有\(\sqrt{n}\)範圍內的質數篩出來,然後用這些篩出來的質數進行質因數分解.最後,如果發現這個數還是大於\(1\),那麼這個數一定是個質數,我們直接讓它的質因子個數等於\(1\)即可.

程式碼

#include<bits/stdc++.h>
using namespace std;

const int N=4e4+10;
bool ip[N];
vector<int> prlist;
void init(){
	for(int i=2;i<N;i++)
		ip[i]=1;
	for(int i=2;i<N;i++){
		for(int j=2;i*j<N;j++)
			ip[i*j]=0;
	}
	for(int i=2;i<N;i++)
		if(ip[i])
			prlist.push_back(i);
	return;
}

int main(void){
	int T;
	init();
	scanf("%d",&T);
	while(T--){
		int a,b,k;
		int ans=0;
		scanf("%d%d%d",&a,&b,&k);
		int ra=a,rb=b;
		for(int i=0;i<prlist.size();i++){
			int j=prlist[i];
			while(a%j==0) {
				ans++;
				a/=j;
			}
			while(b%j==0){
				ans++;
				b/=j;
			}
		}
		if(a!=1)
			ans++;
		if(b!=1)
			ans++;
		if(k<=ans){
			if(k>=2)
				puts("YES");
			else {
				if((ra%rb==0||rb%ra==0)&&ra!=rb)
					puts("YES");
				else 
					puts("NO");
			}
		}
		else 
			puts("NO");
	}
	return 0;
}