题目 | Factorial and Multiple
Denso Create Programming Contest 2022 Winter(AtCoder Beginner Contest 280)
D - Factorial and Multiple
https://atcoder.jp/contests/abc280/tasks/abc280_d
Time Limit: 2 sec / Memory Limit: 1024 MB
Score : $400$ points
Problem Statement
You are given an integer $K$ greater than or equal to $2$.
Find the minimum positive integer $N$ such that $N!$ is a multiple of $K$.
Here, $N!$ denotes the factorial of $N$. Under the Constraints of this problem, we can prove that such an $N$ always exists.
Constraints
- $2\leq K\leq 10^{12}$
- $K$ is an integer.
Input
The input is given from Standard Input in the following format:
K
Output
Print the minimum positive integer $N$ such that $N!$ is a multiple of $K$.
Sample Input 1
30
Sample Output 1
5
- $1!=1$
- $2!=2\times 1=2$
- $3!=3\times 2\times 1=6$
- $4!=4\times 3\times 2\times 1=24$
- $5!=5\times 4\times 3\times 2\times 1=120$
Therefore, $5$ is the minimum positive integer $N$ such that $N!$ is a multiple of $30$. Thus, $5$ should be printed.
Sample Input 2
123456789011
Sample Output 2
123456789011
Sample Input 3
280
Sample Output 3
7
题解
(这题比赛的时候用不正常的方法混过了,现在补一遍正解)
该题要分解质因数,这点应该比较好想,不过之后的处理方式才是重点。即:
对于分解好的数 $K=p_0^{a_0}p_1^{a_1}\dots p_n^{a_n}\ (p_0,p_1,\dots,p_n为质数)$,如何求得最小的 $N!$ 满足 $K\mid N!$
我们可以单独考虑每一个质数,对于 $p_i^{a_i}$,取 $N=p_i\cdot a_i$ 一定能满足条件,但是该答案不一定是最小的。具体举例来说:
如 $3^4$,取 $N=3\cdot4=12$,$N!=12\dots\times9\times\dots\times6\times\dots\times3\times\dots$,可以看见,$9$ 里面实际上包含了两个 $3$,因此我们没有必要令 $N=12$,只需要 $N=9$ 即可。
那么如何求到最小的呢?分解质因数后能保证时间复杂度为 $\log$ 级别,因此我们从直接一个个算就行了。使用变量 $cnt$ 计数,计算 $i\cdot p_i\ (i=1,2,\dots)$ 内含有的 $p_i$ 因子个数 $n$,将 $cnt$ 加上 $n$,直到 $cnt\geq a_i$ 时,$i\cdot p_i$ 便是所求的 $N$。具体举例来说:
如 $3^4$,我们需要 $4$ 个 $3$,从 $1\times3$ 开始,$3$ 含有 $1$ 个 $3$,$6$ 含有 $1$ 个 $3$,$9$ 含有 $2$ 个 $3$,此时已经组成了 $4$ 个 $3$,$N=9$
考虑完单个质数之后,整个 $K$ 的答案便是每个质数因子的答案的最大值。
代码
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
const int MAXN = 1e6 + 10;
int prime[MAXN], primesize = 0;
bool not_prime[MAXN];
void init_prime()
{
not_prime[0] = not_prime[1] = true;
for (int i = 2; i < MAXN; i++)
{
if (!not_prime[i])
prime[primesize++] = i;
for (int j = 0; j < primesize && i * prime[j] < MAXN; j++)
{
not_prime[i * prime[j]] = true;
if (i % prime[j] == 0)
break;
}
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
init_prime();
ll K;
cin >> K;
ll ans = 0;
for (int i = 0; i < primesize; i++)
{
ll prm = prime[i], cnt = 0;
if (prm * prm > K)
break;
while (!(K % prm))
{
K /= prm;
cnt++;
}
ll n = 0;
while (cnt > 0)
{
n += prm;
int x = n;
while (!(x % prm))
{
x /= prm;
cnt--;
}
}
ans = max(ans, n);
}
cout << max(ans, K) << endl;
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi