Solution
题面简洁明了,(就喜欢这种题面)。首先我们需要知道的前导知识,任何一个数,都可以分解为一些素数的幂之积,又叫唯一分解定理,那么对于阶乘这样一个乘积运算,自然也可以进行多次分解质因数。写成素数幂之积。这里给出阶乘求解质因数幂的算法
ll factory(ll n, ll s) { //n!对素数s的求解
ll sum = 0;
while (n) {
n /= s;
sum += n;
}
return sum; //返回幂
} 那么知道了分解质因数之后,首先如果当前答案的阶乘是p的倍数,就说明每一个素数幂大于等于p的对应素数幂,并且这个答案我们希望再小一点,如果当前答案阶乘不是p的倍数,就说明存在一个素数的幂小于p对应素数幂,并且这个答案一定要比求解答案小。符合单调,选择二分。
知道这样两个知识之后这题也就解决了,只存在把这些函数接口接好。
1、对p分解质因数求解到对应素数与对应幂
2、二分答案,对答案也分解质因数,与p的幂对比
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1000;
ll prime_num[maxn], num;//质因数的个数
ll prime[maxn];
void divid(ll n) {
num = 0;
ll i, term;
for (int i = 2; i * i <= n; ++i)
if (n % i == 0) {
term = 0;
while (n % i == 0) {
++term;
n /= i;
}
prime_num[num] = term;
prime[num++] = i;
}
if (n > 1) {
prime[num] = n;
prime_num[num++] = 1;
}
}
ll factory(ll n, ll s) {
ll sum = 0;
while (n) {
n /= s;
sum += n;
}
return sum;
}
bool check(ll x) {
for (int i = 0; i < num; ++i)
if (factory(x, prime[i]) < prime_num[i]) return false;
return true;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
ll x;
scanf("%lld", &x);
if (x <= 2) {
printf("%lld\n", x);
continue;
}
divid(x);
ll l = 1, r = 1e16, ans;
while (l <= r) {
ll mid = l + ((r - l) >> 1);
if (check(mid)) {
ans = mid;
r = mid - 1;
}
else l = mid + 1;
}
printf("%lld\n", ans);
}
return 0;
} !!这里突然发现个更短时间的代码,上面代码跑了457MS,下面跑了144MS。想想也是,毕竟没有二分,掉了这里log的复杂度把,这里说一句不愧是杨大佬,不愧是这次周练第二的男人,tql!!直接跑质因数的幂结果大于等于p的当前素数幂,并计算符合要求的最小次幂的计算结果,并把答案更新。
#include<bits/stdc++.h>
#define js ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
int main() {
int t,n,i,j,ans=0;
js;
cin>>t;
while(t--) {
cin>>n;
ans=0;
for(i=2;i*i<=n;++i) if(n%i==0) { //i是n的一个因子
int cnt=0;
while(n%i==0) { //计算i的幂
n/=i;
++cnt;
}
int tmp=0;
for(j=i;;j+=i) { //找到符合要求的j的最小倍数
for(int p=j;p%i==0;p/=i,++tmp);
if(tmp>=cnt) break;
}
ans=max(ans,j);
}
cout<<max(ans,n)<<endl;
}
} 
京公网安备 11010502036488号