CF1647D (Round #777) 题解 数论

前言:分讨题爬

题面 link

题意:

给定 \(x,d(2\le x,d\le 10^9)\),定义 \(d\) 的倍数为“好数”,不能分解为好数之积的好数为“漂亮数”。
保证 \(x\) 是好数,询问 \(x\) 是否有两种方式分解为漂亮数之积。多组询问。

(注:本文中“分解”和“拆”均指分解为积)

首先,令 \(x=d^k\times s\),其中 \(k>0,d\nmid s\)

那么 \(k-1\)\(d\) 和一个 \(d\times s\) 即为一种分解方案。

接下来考虑构造另一种。

  1. \(k=1\),则显然没有第二种方案。

则接下来的讨论中均有 \(k>1\)

  1. \(s\) 为合数,则将其分解为两个数,分别乘在两个 \(d\) 上,则得到第二种方案。

则接下来的讨论中 \(s\) 均为质数或 \(1\)

那么 \(s\) 拆不动了,只能拆 \(d\)

  1. \(d\) 为质数,那么它就没得拆,所以没有第二种方案。

则现在剩下的情况是 \(k>1\)\(s\) 不是合数,\(d\) 是合数。

  1. \(d\) 中含有不同于 \(s\) 的质因数,则将这个质因数乘在一个 \(d\) 上,剩下的部分与 \(s\) 一起乘在另一个 \(d\) 上,则得到第二种方案,连上被拆的一共需要 \(3\)\(d\),所以需要 \(k>2\)

那么注意到,接下来的讨论中有 \(d=s^q\),其中 \(q>1\)

  1. \(q>2\),则 \(d\) 可以拆为 \(s\)\(s^{q-1}\)。将 \(s^2\)\(s^{q-1}\) 分别乘在一个 \(d\) 上,则得到第二种方案,连上被拆的一共需要 \(3\)\(d\),所以需要 \(k>2\)

  2. \(q=2\),则 \(d\) 可以拆为两个 \(s\)。现在不能将 \(s^2\) 乘在 \(d\) 上了(因为结果不是漂亮数),所以只能将三个 \(s\) 分别乘在三个 \(d\) 上,连上被拆的一共需要 \(4\)\(d\),所以需要 \(k>3\)

注意到后三类可以整合为对 \(s^2\)\(d\) 是否相等的判断。

分类清楚了,代码就容易实现了。加一个质数判断即可。时间复杂度 \(O(T\sqrt{x})\)

code
#include<cstdio>
using namespace std;
int T,x,d,k;
bool check(int n){
	if(n<4) return 1;
	if(n%2==0||n%3==0) return 0;
	for(int i=5;i*i<=n;i+=6)
		if(n%i==0||n%(i+2)==0) return 0;
	return 1;
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&x,&d);
		for(k=0;x%d==0;x/=d,++k);
		if(k<2) printf("NO\n");
		else if(!check(x)) printf("YES\n");
		else if(check(d)) printf("NO\n");
		else printf(k>(x*x==d)+2?"YES\n":"NO\n");
	}
	return 0;
}
posted @ 2022-03-13 10:59  XG0000  阅读(138)  评论(0)    收藏  举报