题目
1294. 樱花 - AcWing题库
给定一个整数 n n n ,求有多少正整数数对 ( x , y ) (x,y) ( x , y ) 满足 1 x + 1 y = 1 n ! \frac{1}{x} + \frac{1}{y} = \frac{1}{n!} x 1 + y 1 = n ! 1 。
输入格式
一个整数 n n n 。
输出格式
一个整数,表示满足条件的数对数量。
答案对 1 0 9 + 7 10^9+7 1 0 9 + 7 取模。
数据范围
1 ≤ n ≤ 1 0 6 1 \le n \le 10^6 1 ≤ n ≤ 1 0 6
输入样例:
2
输出样例:
3
样例解释
共有三个数对 ( x , y ) (x,y) ( x , y ) 满足条件,分别是 ( 3 , 6 ) , ( 4 , 4 ) , ( 6 , 3 ) (3,6),(4,4),(6,3) ( 3 , 6 ) , ( 4 , 4 ) , ( 6 , 3 ) 。
解题
方法一:数学 线性筛 约数个数
思路
本题要求有多少对 x ∈ Z + , y ∈ Z + s . t . 1 x + 1 y = 1 n ! x\in \mathbb{Z}^{+}, y\in \mathbb{Z}^{+} \enspace s.t. \enspace \frac{1}{x} + \frac{1}{y} = \frac{1}{n!} x ∈ Z + , y ∈ Z + s . t . x 1 + y 1 = n ! 1 ,首先通分化简该式:
1 x + 1 y = 1 n ! y + x = x y n ! x n ! + y n ! = x y \begin{aligned}
\frac{1}{x} + \frac{1}{y} &= \frac{1}{n!} \\
y + x &= \frac{xy}{n!} \\
xn! + yn! &= xy \\
\end{aligned}
x 1 + y 1 y + x x n ! + y n ! = n ! 1 = n ! x y = x y
用 x x x 表示 y y y :
x n ! + y n ! = x y x n ! = x y − y n ! x n ! = y ( x − n ! ) y = x n ! x − n ! \begin{aligned}
xn! + yn! &= xy \\
xn! &= xy - yn! \\
xn! &= y(x - n!) \\
y &= \frac{xn!}{x - n!}
\end{aligned}
x n ! + y n ! x n ! x n ! y = x y = x y − y n ! = y ( x − n ! ) = x − n ! x n !
此时问题变为:能找到多少个 x ∈ Z + s . t . y ∈ Z + ⇒ x n ! x − n ! ∈ Z + x\in\mathbb{Z}^{+} \enspace s.t. \enspace y\in\mathbb{Z}^{+} \Rightarrow \frac{xn!}{x - n!}\in\mathbb{Z}^{+} x ∈ Z + s . t . y ∈ Z + ⇒ x − n ! x n ! ∈ Z + ,变形该式:
y = x n ! x − n ! = ( ( x − n ! ) + n ! ) n ! x − n ! = ( x − n ! ) n ! + ( n ! ) 2 x − n ! = n ! + ( n ! ) 2 x − n ! \begin{aligned}
y &= \frac{xn!}{x - n!} \\
&= \frac{((x - n!) + n!)n!}{x - n!} \\
&= \frac{(x - n!)n! + (n!)^2}{x - n!} \\
&= n! + \frac{(n!)^2}{x - n!}
\end{aligned}
y = x − n ! x n ! = x − n ! ( ( x − n ! ) + n ! ) n ! = x − n ! ( x − n ! ) n ! + ( n ! ) 2 = n ! + x − n ! ( n ! ) 2
因为 n ∈ { n ∣ 1 ≤ n ≤ 1 0 6 , n ∈ Z + } n \in \{n | 1\le{n}\le10^6, n \in \mathbb{Z}^{+}\} n ∈ { n ∣ 1 ≤ n ≤ 1 0 6 , n ∈ Z + } ,所以只用保证 ( n ! ) 2 x − n ! \frac{(n!)^2}{x - n!} x − n ! ( n ! ) 2 即可,也就是要保证 x − n ! ∣ ( n ! ) 2 x-n! \mid (n!)^2 x − n ! ∣ ( n ! ) 2 。
那么 x − n ! x-n! x − n ! 有没有可能小于等于 0 0 0 呢?
当 x − n ! ≤ 0 x-n! \le 0 x − n ! ≤ 0 时, x ≤ n ! x \le n! x ≤ n ! ,由 1 x + 1 y = 1 n ! ⇒ 1 y = 1 n ! − 1 x \frac{1}{x} + \frac{1}{y} = \frac{1}{n!} \Rightarrow \frac{1}{y} = \frac{1}{n!} - \frac{1}{x} x 1 + y 1 = n ! 1 ⇒ y 1 = n ! 1 − x 1 可知,当 x ≤ n ! x \le n! x ≤ n ! 时1 x ≥ 1 n ! ⇒ 1 n ! − 1 x ≤ 0 ⇒ 1 y ≤ 0 \frac{1}{x} \ge \frac{1}{n!} \Rightarrow \frac{1}{n!} - \frac{1}{x} \le 0 \Rightarrow \frac{1}{y} \le 0 x 1 ≥ n ! 1 ⇒ n ! 1 − x 1 ≤ 0 ⇒ y 1 ≤ 0 ,与 y ∈ Z + y \in \mathbb{Z}^{+} y ∈ Z + 矛盾,所以 x − n ! > 0 x - n! > 0 x − n ! > 0 。
综上:我们需要找到有多少个 x ∈ Z + x\in\mathbb{Z}^{+} x ∈ Z + 使得 x − n ! ∣ ( n ! ) 2 x-n! \mid (n!)^2 x − n ! ∣ ( n ! ) 2 ,也就是要算出 ( n ! ) 2 (n!)^2 ( n ! ) 2 的(正整数)约数个数。
求 ( n ! ) 2 (n!)^2 ( n ! ) 2 的约数个数可以先用线性筛 筛出范围 [ 1 , n ] [1, n] [ 1 , n ] 之间的质数,然后借助勒让德定理 求出 n ! n! n ! 的质因数分解中,每个质数的次数(指数)。
根据算术基本定理 把 n ! n! n ! 可以质因数分解为:n ! = p 1 α 1 × p 2 α 2 × ⋯ × p k α k n! = p_1^{\alpha_1} \times p_2^{\alpha_2} \times \cdots \times p_k^{\alpha_k} n ! = p 1 α 1 × p 2 α 2 × ⋯ × p k α k ;那么 ( n ! ) 2 (n!)^2 ( n ! ) 2 就可以分解为:
( n ! ) 2 = p 1 2 α 1 × p 2 2 α 2 × ⋯ × p k 2 α k (n!)^2 = p_1^{2\alpha_1} \times p_2^{2\alpha_2} \times \cdots \times p_k^{2\alpha_k}
( n ! ) 2 = p 1 2 α 1 × p 2 2 α 2 × ⋯ × p k 2 α k
此时 ( n ! ) 2 (n!)^2 ( n ! ) 2 的约数个数为:
f ( ( n ! ) 2 ) = ∏ i = 1 k ( 2 α i + 1 ) = ( 2 α 1 + 1 ) ( 2 α 2 + 1 ) ⋯ ( 2 α k + 1 ) f((n!)^2) = \prod_{i=1}^{k}{(2\alpha_i + 1)} = (2\alpha_1 + 1)(2\alpha_2 + 1) \cdots (2\alpha_k + 1)
f ( ( n ! ) 2 ) = i = 1 ∏ k ( 2 α i + 1 ) = ( 2 α 1 + 1 ) ( 2 α 2 + 1 ) ⋯ ( 2 α k + 1 )
代码
import java.util.*;
import java.io.*;
public class Main {
static final int N = (int) 1e6 + 10, MOD = (int) 1e9 + 7;
static int[] primes = new int[N];
static int cnt;
static boolean[] np = new boolean[N];
static void sieve(int n) {
for (int x = 2; x <= n; ++x) {
if (!np[x]) primes[cnt++] = x;
for (int i = 0; primes[i] <= n / x; ++i) {
np[primes[i] * x] = true;
if (x % primes[i] == 0) break;
}
}
}
static int count(int n, int p) {
int res = 0;
while (n > 0) res += n /= p;
return res;
}
public static void main(String[] args) throws IOException {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
in.nextToken(); int n = (int) in.nval;
sieve(n);
long ans = 1L;
for (int i = 0; i < cnt; ++i) {
ans = ans * (2 * count(n, primes[i]) + 1) % MOD;
}
System.out.println(ans);
}
}
评论区