AcWing 1296. 聪明的燕姿
原题链接
中等
作者:
不知名的fE
,
2024-11-25 14:22:25
,
所有人可见
,
阅读 1
样例
import java.util.*;
import java.io.*;
public class Main {
//预处理(筛出)5 * 10^5的质数:500000 * 500000 > 2 * 10^9,即取根号A
//不会出现两个大于500000的质因子乘积的答案
static final int N = 500010;
static PrintWriter out = new PrintWriter(System.out);
static int[] primes = new int[N], ans = new int[N];
static boolean[] st = new boolean[N];
static int idx, len, s;
public static void main(String[] args) {
get_primes(N - 1);//预处理
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
s = sc.nextInt();
len = 0;
//primes下标从0开始的
dfs(-1, 1, s);
Arrays.sort(ans, 0, len);
out.println(len);
if (len != 0) {
for (int i = 0; i < len; i++) out.print(ans[i] + " ");
out.println();
}
}
out.flush();
}
static void get_primes(int u) {
for (int i = 2; i <= u; i++) {
if (!st[i]) primes[idx++] = i;
for (int j = 0; i * primes[j] <= u; j++) {
st[i * primes[j]] = true;
if (i % primes[j] == 0) break;
}
}
}
/*
last : 上一个质数的下标
pro : 记录当前的大小
remain : 剩下的数值
*/
static void dfs(int last, int pro, int remain) {
if (remain == 1) {
ans[len++] = pro;
return;
}
/*
若出现一个大于500000(P)的质因子满足条件的话
那么有: (1 + P) * pro = S, remain = S / pro
就有1 + P = S / pro => 1 + P = remain
首先要满足比前一个质数primes[last]大(注意对last = -1特判)
P为质数, 既有 P = remain - 1判断质数is_prime(remain - 1)
注意这里不需要return
因为这里只是进行对(1 + P) * pro = S的判定,既有剪枝也有对大质因子的判定
剪枝的时候:先考虑remain = P + 1,再考虑remain = 1 + P + P^2 + ... + P^k,不能return
对大质因子的判定时也不能return,因为该P可以表示为其他p的形式:
比如对于质数2的指数链:1 + 2^1 + 2^2 + ... + 2^18 = 2^19 - 1 = 524288 - 1 = 524287(质数)
本质都是一样的
下面是重复计算问题:
显然对于大质因数是不会重复计算的
讨论剪枝的时候
下面只会枚举到sqrt(remain)不会枚举到 remain - 1的
因此不会重复计算
*/
if (remain - 1 > (last < 0 ? 0 : primes[last]) && is_prime(remain - 1))
ans[len++] = pro * (remain - 1);
//不存在比sqrt(remain)大的两个数相乘等于remain
for (int i = last + 1; primes[i] <= remain / primes[i]; i++) {
int p = primes[i];
for (int j = 1 + p, t = p; j <= remain; t *= p, j += t)
if (remain % j == 0)
dfs(i, pro * t, remain / j);
}
}
//判断是否是质数
static boolean is_prime(int n) {
if (n < N) return !st[n];
for (int i = 0; primes[i] <= n / primes[i]; i++) {
if (n % primes[i] == 0) return false;
}
return true;
}
}