链接: 202312-2因子化简.
样例输入(便于复制粘贴):
3
2155895064 3
2 2
10000000000 10
样例输出:
2238728
1
10000000000
【题目所需代码模块】
1.质数判断
具体判断某一个数x是否为质数,从2开始向后遍历到x(记为i),如果x%i==0,则证明x除了1和自身还有其他因子,也就是x是一个合数。
简单粗暴版本代码
bool IsZhi(int x)//判断是否为质数
{
for(int i=2;i<=x;i++)
{
if(x%i==0)return false;
}
return true;
}
一个数的约数是成对存在,也就是说:如果一个数是合数,则这个数拆分为a*b的形式时,a和b中必有一者是小于√x,一者是大于√x,例如100,你找到个约数5,那么一定有个约数20,因为100/5=20。
这也就是意味着:判断一个数是否除了1和自身,没有其他因子时,只需要从i=2遍历到i=√x就可以了。 于是便有了下面优化后的代码。
优化后版本代码
bool IsZhi(int x)//判断是否为质数
{
for(int i=2;i*i<=x;i++)//这里也可以写成i<sqrt(x),也可以写成i<x/i
{
if(x%i==0)return false;
}
return true;
}
2.求解合数因子的指数
问:如果该数是一个合数,并且已经知道该合数有质数因子i,则如何求解这个质数因子的次幂呢?
答:利用余数和除数(由于很久没有写代码题了,手很生,所以这里就浅浅记录一下)
代码
int beishu=0;
while(n%i==0)//如果n取余i等于0,则意味着n中还含有一个因子i,也就需要beishu++
{
n=n/i;
beishu++;
}
【题目分析】
1. 90分超时思路:
从i=2开始遍历到n:
- 依次判断i是否为质数,如果i是质数,则求n中有多少个i,也就是i的指数(或叫幂次)beishu;
- 之后判断幂次是否大于等于阈值k,如果大于等于k,则将i的beishu次方留下来。
优化1:
由于判断i是否为质数,超时。
于是优化,将判断质数给省略掉,这是因为,i是从2开始遍历的,从小的质数开始遍历,之后并求出了n中有多少个i;因此类推,这就相当于将之后n的合数因子给逐步化简了。
优化2:
由于从i=2开始遍历到n ,超时。
于是优化,这里的优化原因和 ‘ 质数判断代码模块’ 的优化原理一毛一样,所以下面就复制粘贴一下原因:一个数的约数是成对存在,也就是说:如果一个数是合数,则这个数拆分为a*b的形式时,a和b中必有一者是小于√x,一者是大于√x,例如100,你找到个约数5,那么一定有个约数20,因为100/5=20。
这也就是意味着:判断一个数是否除了1和自身,没有其他因子时,只需要从i=2遍历到i=√x就可以了。 于是便有了下面优化后的代码。
2.90分啰嗦版代码
#include <iostream>
#include <cmath>
using namespace std;
bool IsZhi(int x)//判断是否为质数
{
for(int i=2;i*i<=x;i++)
{
if(x%i==0)return false;
}
return true;
}
void Sample(long long n, int k)
{
//int reserve_num=0;
long long int reserve_sum=1;
for(int i=2;i*i<n;i++)//因为题目中说k是大于1的,故只需遍历到根号n即可
{
//bool zhishu=IsZhi(i);
//if(zhishu==true)//因为从2开始除,所以后面的合数都被排除了
//{
int beishu=0;//,cur=n;
while(n%i==0)
{
n=n/i;
beishu++;
}
if(beishu>=k)
{
//reserve_num+=1;
long long dot=pow(i,beishu);
reserve_sum*=dot;
//n/=dot;
//cout<<dot<<"========"<<reserve_sum<<"========="<<i<<endl;
}
//if(i<200)
//cout<<i<<"========"<<endl;
//}
}
//if(reserve_num==0)cout<<"1"<<endl;
//else cout<<reserve_sum<<endl;
cout<<reserve_sum<<endl;
}
int main()
{
int q,k;
long long n;
cin>>q;
for(int i=0;i<q;i++)
{
cin>>n>>k;
Sample(n,k);
}
return 0;
}
3.100分完整代码
#include <iostream>
#include <cmath>
using namespace std;
void Sample(long long n, int k)
{
long long int reserve_sum=1;
for(int i=2;i*i<n;i++)//因为题目中说k是大于1的,故只需遍历到根号n即可
{
int beishu=0;
while(n%i==0)
{
n=n/i;
beishu++;
}
if(beishu>=k)
{
long long dot=pow(i,beishu);
reserve_sum*=dot;
}
}
cout<<reserve_sum<<endl;
}
int main()
{
int q,k;
long long n;
cin>>q;
for(int i=0;i<q;i++)
{
cin>>n>>k;
Sample(n,k);
}
return 0;
}