题意很简单,给定一个整数x,范围<1e12,求最小的正整数n,使得n的阶乘可以整除x
将x分解成素数积,可以注意到一个事实,即n的阶乘可以整除x,那么对于任意x的一个素数,将n的阶乘分解成素数积后,该素数的数量一定大于等于x的数量。
对于每个素数,我们单独考虑
假设当前素数为x,数量为y,显然n的大小具有二分性,即n越大,对应数目一定越多。
我们可以二分n,直至找到最小的n,满足n的阶乘的x的因子数目>=y
如何二分:
考虑容斥,对于素因子x来说,具有该因子的数字一定是x的倍数,但一个数字显然可能具有多个x因子,所以容斥,枚举x的1,2,3...次方的倍数对答案贡献
也有其他做法:由于x不是很大,素因子不会有很多个,每个素因子的数目也不会很多,我们直接枚举素因子x的倍数,算出每个倍数有多少个素因子即可
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
#define int long long
typedef pair<int, int>pii;
typedef pair<int, double>pid;
typedef pair<int, pii>piii;
const int mod = 1e9 + 7;
const int N = 2e5 + 100;
int poww(int a, int b) { int ans = 1; if (b == 0)return 1; for (int i = 1; i <= b; i++)ans = ans * a; return ans; }
unordered_map<int, int>syz;
int ck(int n, int x, int y)
{
int ds = x;
int sum = 0;
int bk = x;
while (ds <= n)
{
sum += n / ds;
if (sum >= y)return 1;
ds = ds * x;
if (ds <= bk)return 0;
bk = ds;
}
return 0;
}
void solve()
{
int n; cin >> n;
int fl = 0;
int bk = n;
for (int i = 2; i * i <= n; i++)
{
if (n % i == 0)fl = 1;
}
if (fl == 0)cout << n;
else
{
int mx = 0;
for (int i = 2; i * i <= n; i++)
{
if (n % i == 0)
{
while (n % i == 0)
{
syz[i]++;
n /= i;
}
}
}
if (n > 1)syz[n]++;
int ans = -1;
for (auto [x, y] : syz)
{
int l = 1, r = 1e12;
while (l < r)
{
int mid = (l + r) >> 1;
if (ck(mid, x, y))r = mid;
else l = mid + 1;
}
ans = max(ans, l);
}
cout << min(ans, bk);
}
}
signed main()
{
ios::sync_with_stdio(0); cout.tie(0); cin.tie(0);
int t = 1;
// cin >> t;
while (t--)solve();
}