1. 问题描述:
问题描述
给定一个正整数n,求一个正整数p,满足p仅包含n的所有素因子,且每个素因子的次数不大于1
输入格式
一个整数,表示n
输出格式
输出一行,包含一个整数p。
样例输入
1000
样例输出
10
数据规模和约定
n<=10^12
样例解释:n=1000=2^3*5*3,p=2*5=10
2. 思路分析:
① 这道题目主要考察的是分解公因式的问题,这里可以使用两层的嵌套for循环,第二层的for循环可以用来表示表示多个相同的素数因子,第一层的循环可以从2到n / 2,而第二层循环中假如我们可以被 i 整除那么我们可以将n一直除以i,第一次的时候会把n中所有能够分解成2的素数因子除掉,第二次的时候所有能够分解成3的素数因子除掉(没有就不执行)当i = 4的时候因为之前已经将2的素数因子除掉了,所以接下来的不可能被4整除,所以第一层i从2到n / 2可以用来表示当前的素数因子
② 其中需要注意的是题目的数据规模是小于等于10 ^ 12,小于当我们发现当前的n小于素数因子的时候这个时候应该退出循环,因为接下来当前的n不能够被大于它的素数因子整除了,所以直接退出循环就可以了,假如不提前退出循环那么程序肯定超时
所以来说提前的这个判断是非常重要的
③ 我们可以在确定一个素数因子之后把它乘起来,只有当我们进入第二层循环的时候才能够把这个素数因子加进来(说明n中包含了这个素数因子),因为有的不能够被素数因子整除,所以需要增加一个变量来确定是否进入了第二层的循环并且进入下一轮循环的时候将其恢复到原来的标志
for(int i = 2; i <= t / 2; i++){
while(n % i == 0){
n /= i;
flag = 1;
}
if(flag == 1) {
res *= i;
}
if(n < i) break;
flag = 0;
}
}
④ 除了上面的在中间过程记录素数因子之外,我们还可以使用Set数据结构来记录当前满足条件的素数因子,使用Set集合是因为它可以存进去不重复的素数因子,这样在最后的时候迭代Set集合,把其中的值累乘起来这样就可以了
for(int i = 2; i <= t / 2; i++){
while(n % i == 0){
set.add((long) i);
n /= i;
}
if(n < i) break;
}
set.add(n);
⑤ 还有一个问题就是在第一层的循环应该使用一个辅助的变量t来等于n,因为在循环中n是不断在进行变化的,但是素数因子的总的数量是不能够改变的,这个是容易出现错误的一个点
3. 代码如下:
① 不使用Set集合:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Long n = sc.nextLong();
int flag = 0;
Long t = n;
Long res = 1L;
for(int i = 2; i <= t / 2; i++){
while(n % i == 0){
n /= i;
flag = 1;
}
if(flag == 1) {
res *= i;
}
if(n < i) break;
flag = 0;
}
System.out.println(res * n);
sc.close();
}
}
② 使用Set集合:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
public class Main {
static Set<Long> set = new HashSet<Long>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Long n = sc.nextLong();
Long t = n;
Long res = 1L;
for(int i = 2; i <= t / 2; i++){
while(n % i == 0){
set.add((long) i);
n /= i;
}
if(n < i) break;
}
set.add(n);
Iterator<Long> iterator = set.iterator();
while(iterator.hasNext()){
res *= iterator.next();
}
System.out.println(res);
sc.close();
}
}