链接:HDU6623 Minimal Power of Prime
题意:
给出 T ( ≤ 50000 ) T(\le50000) T(≤50000)个 n ( ≤ 1 0 18 ) n(\le10^{18}) n(≤1018),对 n n n进行质因数分解,问分解后质因数的幂最小的是多少?
例如: 108 = 2 2 ∗ 3 3 108=2^2*3^3 108=22∗33,所以质因数的幂最小是 2 2 2
分析:
直接对 n n n进行质因数分解的话时间复杂度会达到 O ( T ∗ n 1 4 ) O(T*n^{\frac{1}{4}}) O(T∗n41),会超时。
我们可以仅考虑 1 0 18 ∗ 1 5 10^{18*\frac{1}{5}} 1018∗51,即 1 0 3.6 10^{3.6} 103.6以内的质因数进行考虑( 1 0 3.6 10^{3.6} 103.6内质数只有500多个),如果这些质因数最终没有将 n n n完全分解(没能令 n = 1 n=1 n=1),很明显 n n n剩下的可能质因数一定 > 1 0 3.6 \gt10^{3.6} >103.6,那么答案只有4种情况。
- n = p 4 n=p^4 n=p4,则ans=min(ans, 4)
- n = p 3 n=p^3 n=p3,则ans=min(ans, 3)
- n = p 2 或 n = p 1 2 ∗ p 2 2 n=p^2或n=p_1^2*p_2^2 n=p2或n=p12∗p22,则ans=min(ans, 2)
- 除以上3种情况外,剩余的质因数幂最小一定为1,即ans=1
以下代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=4000; //约等于10^3.6
int p[maxn],cnt=0;
bool vis[maxn];
void get_prime() //欧拉筛得到质数表
{
for(int i=2;i<=maxn;i++)
{
if(!vis[i])
p[++cnt]=i;
for(int j=1;j<=cnt&&i*p[j]<=maxn;j++)
{
vis[i*p[j]]=true;
if(i%p[j]==0)
break;
}
}
}
int solve(LL x)
{
if(x==1)
return 0;
int ans=INF,tot;
for(LL i=1;i<=cnt;i++)
{
tot=0;
while(x%(LL)p[i]==0)
{
tot++;
x/=(LL)p[i];
}
if(tot==0)
continue;
ans=min(ans,tot);
if(x==1) //分解完成,说明所有质因数都在10^3.6以内
return ans;
}
LL k;
k=round(pow(1.0*x,1.0/4.0));
if(k*k*k*k==x)
return min(ans,4);
k=round(pow(1.0*x,1.0/3.0));
if(k*k*k==x)
return min(ans,3);
k=round(pow(1.0*x,1.0/2.0));
if(k*k==x)
return min(ans,2);
return 1;
}
int main()
{
get_prime();
int T;
scanf("%d",&T);
while(T--)
{
LL n;
scanf("%lld",&n);
printf("%d\n",solve(n));
}
return 0;
}