1 Problem
题意:给定
n
(
n
≤
1
0
18
)
n(n\leq10^{18})
n(n≤1018),求
n
n
n唯一分解中质因数幂次最小值吗,
T
T
T个询问
(
T
≤
5
⋅
1
0
4
)
(T\leq5\cdot10^4)
(T≤5⋅104)(是不是很简洁呀)
2 Solve
2.1 50 10分
T
≤
1
0
3
T\leq10^3
T≤103,
n
≤
1
0
3
n\leq10^3
n≤103
对每个询问,从
2
2
2到
s
q
r
t
(
n
)
sqrt(n)
sqrt(n)枚举
i
i
i,对每个
i
i
i
while(n%i==0){n/=i;cnt++;}
if(cnt) ans = min(ans,cnt)
;
然而实测能过
n
≤
1
0
18
n\leq10^{18}
n≤1018(雾)
(不知道是不是数据太水了)
2.2 30分
T
≤
1
0
3
,
n
≤
1
0
9
T\leq10^3,n\leq10^9
T≤103,n≤109
同上,加个素数筛
然而得分还没有直接枚举高
数组开不下是真的伤
2.3 正解(玄学)
(证明附在解法后,和我一样一脸懵逼的可以跳过)
先处理出
1
0
18
5
\sqrt[5]{10^{18}}
51018以内的素数(只有 不到600个)
对每个询问
n
n
n,
先暴力除掉这些素数,同时记录
m
i
n
_
p
o
w
min\_pow
min_pow
然后对除掉这些素数后的
n
n
n,依次判断:
如果
n
n
n为
k
4
k^4
k4,
a
n
s
=
m
i
n
(
a
n
s
,
4
)
ans=min(ans,4)
ans=min(ans,4)
如果
n
n
n为
k
3
k^3
k3,
a
n
s
=
m
i
n
(
a
n
s
,
3
)
ans=min(ans,3)
ans=min(ans,3)
如果
n
n
n为
k
2
k^2
k2,
a
n
s
=
m
i
n
(
a
n
s
,
2
)
ans=min(ans,2)
ans=min(ans,2)
否则
a
n
s
=
m
i
n
(
a
n
s
,
1
)
=
1
ans=min(ans,1)=1
ans=min(ans,1)=1
输出
a
n
s
ans
ans
没想到吧!我也没有
先呈上程序
#include<bits/stdc++.h>
using namespace std;
template<typename T>
inline void Read(T &n){
char ch;bool flag=0;
while(!isdigit(ch=getchar()))if(ch=='-')flag=1;
for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
if(flag)n=-n;
} //快读
typedef long long ll;
const ll MAXN = 4005;
const double eps = 1e-5; //注意精度(这道题卡精度)
ll Prime[600],top,n,A,B;
bool Is_Prime[MAXN];
int cnt,ans=INT_MAX,T;
bool Is_Pow(ll n,int k){ //判断是否为k次方
double t=pow(n,1.0/k);
return (abs(round(t)-t)<eps);
}
inline void Get_Prime(){ //筛3981(五次根号1e18)以内的质数
memset(Is_Prime,true,sizeof(Is_Prime));
for(register ll i=2; i<=3981; i++){
if(!Is_Prime[i]) continue;
for(register ll j=i; j<=3981; j+=i)
Is_Prime[j]=false;
Prime[++cnt]=i;
}
}
int main(){
// freopen("A.in","r",stdin);
// freopen("A.out","w",stdout);
Get_Prime();
Read(T);
while(T--){
Read(n);
ans=INT_MAX;
top = pow(n,0.2)+5;
for(register int i=1; Prime[i]<=top&&i<=cnt; i++){ //暴力除掉一部分
int tot=0;
while(n%Prime[i]==0){
n /= Prime[i];
tot++;
}
if(tot) ans = min(ans,tot);
}
if(n>1){ //若没分解完,特判
if(Is_Pow(n,4)) ans = min(ans,4);
else if(Is_Pow(n,3)) ans = min(ans,3);
else if(Is_Pow(n,2)) ans = min(ans,2);
else ans = min(ans,1);
}
printf("%lld\n", ans);
}
return 0;
}
3 Prove
若 n n n存在一个素因子 p p p且 p p p指数为1, a n s = 1 ans=1 ans=1
对于其他情况,考虑
n
n
n一定可以表示成
P
2
⋅
Q
3
P^2\cdot Q^3
P2⋅Q3的形式
∀
p
i
(
p
i
∣
n
)
\forall p_i(p_i|n)
∀pi(pi∣n)设其指数为
α
i
\alpha_i
αi
若
α
i
\alpha_i
αi为偶数,则直接丢进
P
P
P里,
若
α
i
\alpha_i
αi为奇数,因为
α
i
̸
=
1
\alpha_i\not=1
αi̸=1,所以
α
i
≥
3
\alpha_i\ge3
αi≥3,所以先将一个
p
i
3
p_i^3
pi3丢进
Q
Q
Q里,那么剩下的
α
i
\alpha_i
αi一定为偶数,然后丢进
P
P
P中
也就是说 n = P 2 ⋅ Q 3 ⇔ a n s > 1 n=P^2\cdot Q^3\Leftrightarrow ans\gt1 n=P2⋅Q3⇔ans>1
假设我们已经得到了处理好的
P
,
Q
P,Q
P,Q,那么
m
i
n
(
P
,
Q
)
<
=
n
5
min(P,Q)<=\sqrt[5]n
min(P,Q)<=5n,若不然
P
2
⋅
Q
3
≥
m
i
n
(
P
,
Q
)
5
>
n
P^2\cdot Q^3\ge min(P,Q)^5>n
P2⋅Q3≥min(P,Q)5>n
所以先暴力除掉
n
5
\sqrt[5]n
5n以内的素数,然后考虑剩下的素数
p
1
,
p
2
.
.
.
p
k
p_1,p_2...p_k
p1,p2...pk,设指数为
q
1
,
q
2
.
.
.
q
k
q_1,q_2...q_k
q1,q2...qk
若
∑
q
i
≥
5
\sum q_i\ge5
∑qi≥5,那么
∏
p
i
q
i
>
m
i
n
(
p
i
)
∑
q
i
≥
m
i
n
(
p
i
)
5
=
n
\prod p_i^{q_i}>min(p_i)^{\sum q_i}\geq min(p_i)^5=n
∏piqi>min(pi)∑qi≥min(pi)5=n,舍
所以
∑
q
i
<
5
\sum q_i<5
∑qi<5,同时注意到
∀
q
i
>
1
\forall q_i>1
∀qi>1,那么只有这几种情况:
n
=
p
2
n=p^2
n=p2
n
=
p
3
n=p^3
n=p3
n
=
p
2
⋅
q
2
n=p^2\cdot q^2
n=p2⋅q2
n
=
p
4
n=p^4
n=p4
然后判断一下
n
n
n是否为2/3/4次方就好了
特别的,为了方便码,对于 a n s = 1 ans=1 ans=1的情况,若剩下的 n n n不是任何次方, a n s = 1 ans=1 ans=1
大功告成!