202312-2 因子化简

本文介绍了如何优化质因数分解算法,通过判断因子而不是质数来确定合数因子的指数,以及利用约数对的存在性减少计算量,以提高代码效率。

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

链接: 202312-2因子化简.

题目1
题目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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值