【CCF CSP】202312-2 因子化简

1. 题目要求

在这里插入图片描述

2. 前提

①算术基本定理:任一大于1的自然数,要么本身是质数,要么可以分解为几个质数之积,且这种分解是唯一的。
②质数:除了1和它本身,没有别的数可以整除它。(1不是质数,2是质数)

3. 思想

将n分解成的不同素因子相乘的形式,当某一个素因子的个数≥k时,就保留下来,即temp *= pow(i,t);

问题是,如何分解呢?
最简单的方法是,i从2到n进行遍历,若是能整除n,则输出i,并且n=n/i。

注1:我看其他大佬的代码都没有判断i是否质数,应该是因为不需要,例如,若2为其质因子,全部输出后,则当i=4时,就不可能再整除n了。
注2:若n本身为质数 或者 n的某个质因子的对应的指数为1,则i遍历之后,n>1;否则n=1. (例如17,14,28,反例25)

但为了提高时间效率,可以从多个方面进行改进:

改进点1:质因子的最大值不超过n的平方根+1(例如6=2*3)
改进点2:质因子除了2之外,只能是奇数(感觉对时间复杂度的改进不大,反而使代码看起来更丑陋了)

最终代码如下所示。

3. 代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
long long primeFactor(long long n, long long k){
    int t = 0;//素数因子的阶数
    long long temp = 1;//记录最终返回值
    // 除去所有 2 的倍数的因子
    while(n % 2 == 0){
        t++;
        n /= 2;
    }
    if(t>=k){
        temp = powl(2,t);
    }
    // 经过第二步, 此时 n 一定为奇数
    // 并且不存在偶数的素因子
    // 所以我们可以跳过所有偶数 (i += 2)
    for(int i = 3; i <= sqrt(n); i += 2){
        //除去所有 i 的倍数的因子
        t=0;
        while(n % i == 0){
            t++;
            n /= i;
        }
        if(t>=k){
            temp *= powl(i,t);
        }
    }
    //此处为了防止剩下的素因子是一个大于 2 的素数
    if(n > 2){
        if(k<=1)
            temp *= powl(n,t);
    }
    return temp;
}
int main(){
    int hang;
    cin >> hang;
    vector<vector<long long> > arr(hang,vector<long long>(2));
    for(int i=0; i < hang; i++){
        cin>>arr[i][0];
        cin>>arr[i][1];
    }
    for(int i=0; i < hang; i++){
        cout << primeFactor(arr[i][0],arr[i][1])<<endl;
    }
    return 0;
}

6是如何分解的?
首先除去2,n=3,所以2为一个质因子;
由于3<根号3,所以跳过循环;
由于n>2,所以另一个质因子为3.

4. 结果

在这里插入图片描述

5. 总结

写代码时,遇到几个bug
①对于32位编译器,int和long都是用4个字节表示的;对于64位编译器,long是用8个字节表示的。所以我最开始用long表示,2155895064这个测试输入数据超出其表示长度了。
②pow(x,y):求x的y次幂,但是由于是double类型的,截断小数部分之后,某些值的结果与实际值总是相差1。 换成powl(x,y)之后,就正常了。

6. 参考代码


https://blog.csdn.net/m0_74172965/article/details/135090693?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-135090693-blog-134935729.235%5Ev40%5Epc_relevant_3m_sort_dl_base2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-135090693-blog-134935729.235%5Ev40%5Epc_relevant_3m_sort_dl_base2&utm_relevant_index=2

https://www.cnblogs.com/1pha/p/7749828.html#:~:text=%E5%AF%B9%E4%BA%8E%E6%B1%82%E4%B8%80%E4%B8%AA%E6%95%B0%20n%20%E7%9A%84%E6%89%80%E6%9C%89%E8%B4%A8%E5%9B%A0%E5%AD%90%2C%20%E9%80%9A%E5%B8%B8%E6%98%AF%E5%9C%A8%20%5B2%2C%20sqrt%20%28n%29%5D%20%E7%9A%84%E8%8C%83%E5%9B%B4%E5%86%85%E6%9E%9A%E4%B8%BE,%E4%BB%A5%E5%8F%8A%20n%20%2F%20i.%20%E7%84%B6%E8%80%8C%2C%20Vishwas%20Garg%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%80%E7%A7%8D%E6%9B%B4%E4%B8%BA%E9%AB%98%E6%95%88%20%28logN%29%E7%9A%84%E6%B1%82%E4%B8%80%E4%B8%AA%E6%95%B0%E6%89%80%E6%9C%89%E7%B4%A0%E5%9B%A0%E5%AD%90%E7%9A%84%E6%96%B9%E6%B3%95.

https://blog.csdn.net/LZXloveGYD/article/details/71340090?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-4-71340090-blog-109158648.235%5Ev40%5Epc_relevant_3m_sort_dl_base2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-4-71340090-blog-109158648.235%5Ev40%5Epc_relevant_3m_sort_dl_base2&utm_relevant_index=9

  • 26
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值