题目
试题编号 | 202312-2 |
---|---|
试题名称 | 因子化简 |
时间限制 | 2s |
内存限制 | 512MB |
问题描述 | |
输入输出 | |
样例 | |
样例解释 |
题目分析
我的思路很简单。
先埃氏筛素数法筛一下
2
−
1
0
5
2-10^{5}
2−105的素数。这里要知道这样一个素数原理,即:
任意的大于0整数,其质因子分解最多只有1个质因子大于
n
\sqrt{n}
n 且该因子一定是一次幂。
比如:
42
=
2
∗
3
∗
7
42=2*3*7
42=2∗3∗7。7是大于
42
\sqrt{42}
42的质因子,又比如
36
=
2
2
∗
3
2
36=2^2*3^2
36=22∗32没有大于6的质数因子。
很简单自己证明下就可以。n最大是
1
0
10
10^{10}
1010,因此只需要筛一下
2
−
1
0
5
2-10^{5}
2−105以内的素数即可。在筛选后执行下面的步骤。若
p
r
i
m
e
i
prime_i
primei不大于
n
\sqrt{n}
n,则判断
n
%
(
p
r
i
m
e
i
k
)
=
=
0
n \%(prime_i^k)==0
n%(primeik)==0
如果不为0,则说明要舍弃这个素数的项,从k开始往0找
p
r
i
m
e
i
prime_i
primei的指数count_k(因为k不超过10,从10开始向下找不费时间)。找到后更新
n
=
n
/
p
r
i
m
e
i
c
o
u
n
t
_
k
n=n/prime_i^{count\_k}
n=n/primeicount_k同时要记录一个nn,是将
p
r
i
m
e
i
prime_i
primei完全除尽的结果。一直找到某个素数大于n或者等于n。这里注意下等于n的话要直接输出1,因为k不会为1。
在把
2
−
1
0
5
2-10^{5}
2−105内的所有素数都找完后还没输出的话(sign=0),那么就判断下nn的值,如果nn不是1,说明nn等于那个大于
n
\sqrt{n}
n的素数,就输出n/nn即可(因为大于
n
\sqrt{n}
n的素数指数一定是1).如果nn为1,那就输出n。
AC代码(100分)
#include <stdio.h>
#include <string.h>
#include <vector>
#include <cmath>
#include <iostream>
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define rep(i,a,n) for(ll i=a;i<n;i++)
using namespace std;
ll quick(ll d,int z){
ll ans=1;
while(z){
if(z&1)
ans*=d;
d*=d;
z>>=1;
}
return ans;
}
int q,k;
ll n;
const int p=100000;
int prime[100001];
vector<int>qq;
void set_prime(int x){
rep(i,2,x+1){
int index=2;
if(prime[i]==0){
qq.push_back(i);
while(index*i<=x){
if(!prime[index*i]){
prime[index*i]=1;
}
index++;
}
}
}
}
int main(){
mem(prime);
set_prime(p);
scanf("%d",&q);
while(q--){
scanf("%lld%d",&n,&k);
if(n<=p&&prime[n]==0){
printf("%lld\n",1);
}
else{
ll nn=n;
double sqn=sqrt(n);
int sign=0;
rep(i,0,qq.size()){
int y=qq[i];
if(y>sqn)break;
if(n==y){
printf("%lld\n",1);
sign=1;
break;
}
else if(n<y){
printf("%lld\n",n);
sign=1;
break;
}
else if(n%y!=0)continue;
else{
int count_k=0;
ll temp=n;
while(temp%y==0){
count_k++;
temp/=y;
nn/=y;
}
if(count_k<k){
n=temp;
}
}
}
if(!sign){
if(nn!=1)printf("%lld\n",n/nn);
else printf("%lld\n",n);
}
}
}
return 0;
}
/*
3
2155895064 3
2 2
10000000000 10
*/