2019.8.3模拟赛 T1

本文详细介绍了如何解决数论问题,寻找一个正整数n(n≤10^18)的质因数幂次的最小值。分别探讨了枚举方法、筛法以及优化后的解决方案,并提供了证明过程,通过分析n为不同次方的情形来确定最小值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 Problem

题意:给定 n ( n ≤ 1 0 18 ) n(n\leq10^{18}) n(n1018),求 n n n唯一分解中质因数幂次最小值吗, T T T个询问 ( T ≤ 5 ⋅ 1 0 4 ) (T\leq5\cdot10^4) (T5104)是不是很简洁呀

2 Solve

2.1 50 10分

T ≤ 1 0 3 T\leq10^3 T103 n ≤ 1 0 3 n\leq10^3 n103
对每个询问,从 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} n1018(雾)
不知道是不是数据太水了

2.2 30分

T ≤ 1 0 3 , n ≤ 1 0 9 T\leq10^3,n\leq10^9 T103,n109
同上,加个素数筛
然而得分还没有直接枚举高
数组开不下是真的伤

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 P2Q3的形式
∀ p i ( p i ∣ n ) \forall p_i(p_i|n) pi(pin)设其指数为 α 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 αi3,所以先将一个 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 &gt; 1 n=P^2\cdot Q^3\Leftrightarrow ans\gt1 n=P2Q3ans>1

假设我们已经得到了处理好的 P , Q P,Q P,Q,那么 m i n ( P , Q ) &lt; = n 5 min(P,Q)&lt;=\sqrt[5]n min(P,Q)<=5n ,若不然 P 2 ⋅ Q 3 ≥ m i n ( P , Q ) 5 &gt; n P^2\cdot Q^3\ge min(P,Q)^5&gt;n P2Q3min(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 qi5,那么 ∏ p i q i &gt; m i n ( p i ) ∑ q i ≥ m i n ( p i ) 5 = n \prod p_i^{q_i}&gt;min(p_i)^{\sum q_i}\geq min(p_i)^5=n piqi>min(pi)qimin(pi)5=n,舍
所以 ∑ q i &lt; 5 \sum q_i&lt;5 qi<5,同时注意到 ∀ q i &gt; 1 \forall q_i&gt;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=p2q2
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

大功告成!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值