Loading

【题解】Luogu P10411 「QFOI R2」树色尤含残雨

1. 题目大意

给定一个正整数 \(x\),每次可以将 \(x\) 除以两个质数的正整数次方的积,直到不能再除为止。求除完之后最小的 \(x\)

2. 思路分析&代码实现

① 分解质因数

因为要将 \(x\) 除以质数的正整数次方,所以需要把 \(x\) 分解质因数。

分解质因数的代码很好写。这里用结构体 \(a\) 来存储质因数的信息,其中 \(n\) 存储质因数,\(cnt\) 存储质因数的次数。

for(int i=2;i<=x/i;i++){
		if(x%i==0){
			a[++tot].n=i;
			while(x%i==0){
				x/=i;
				a[tot].cnt++;
			} 
			ans=max(ans,a[tot].cnt);
		} 
	}
	if(x>1){
	    a[++tot].n=x;
	    a[tot].cnt=1;
	    ans=max(ans,a[tot].cnt);
	}

最坏时间复杂度 \(O(\sqrt n)\)\(\sqrt{10^9} \approx 31622.78\),显然可以通过本题。

② 找出最小值

分类讨论。

情况1:\(tot=1\)

如果 \(tot=1\),那么有以下两种情况:

I. \(x\) 为质数
II. \(x\) 为完全平方数

这两种情况显然都不能进行任何题目要求的除法操作,直接输出 \(x\)

情况2:\(tot\) 为偶数

\(tot\) 为偶数时就说明 \(x\) 有偶数个质因子,这些质因子两两搭配便可进行除法操作,除完之后一定等于 \(1\)

情况3:\(tot\) 为奇数且不为 \(1\)

你可能会对上文分解质因数代码中 \(ans\) 变量的用处感到疑惑,现在用出来了。

I. \(ans=1\)

\(ans=1\) 意味着 \(x\) 的所有质因子的次数都是 \(1\),而 \(x\) 又有奇数个质因子,那么在配对时必将有一个质因子单出来,那我们输出 \(x\) 的最小质因子即可。

II. \(ans>1\)

\(ans>1\) 意味着 \(x\) 有质因子可以被拆到两组配对中,单出来的质因子可以被配对,所以输出 \(1\)

代码是一个简单的分支结构(\(x\) 在质因数分解时被处理过了, \(t\) 是原本的 \(x\))。

if(tot==1) cout<<t;
else if(tot%2==0) cout<<1;
else{
	if(ans>1) cout<<1;
	else cout<<a[1].n;
}
	

3. 完整代码

#include<iostream>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
int t,x,tot,ans;
struct prim{
	int n,cnt;
}a[maxn];
int main(){
	cin>>x;t=x;
	for(int i=2;i<=x/i;i++){
		if(x%i==0){
			a[++tot].n=i;
			while(x%i==0){
				x/=i;
				a[tot].cnt++;
			} 
			ans=max(ans,a[tot].cnt);
		} 
	}
	if(x>1){
	    a[++tot].n=x;
	    a[tot].cnt=1;
	    ans=max(ans,a[tot].cnt);
	}
	if(tot%2==0) cout<<1;
	else if(tot==1) cout<<t;
	else{
		if(ans>1) cout<<1;
		else cout<<a[1].n;
	}
	
	return 0;
}

posted @ 2025-12-12 23:33  Seqfrel  阅读(0)  评论(0)    收藏  举报