【题解】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;
}

浙公网安备 33010602011771号