解题过程的小记录,如有错误欢迎指出。
难度:三星(找素数模板+找因数模板)
题目分析
给出一个数n,找出它的素数因数队列
注意点
- 题干说的是n为正整数范围,所以要考虑1的情况
- 题干说n是long int,要考虑过程中是否有溢出(我把涉及的变量都改为long long了,可以过)
我的解题过程
思路
- 找出<=sqrt(n)的质数【n的质因数一定全部<=sqrt(n)或者有一个大于】
- 确认找出的质数是否是n的因数,如果是的话,有几个
- 按格式输出
【本题还是要看看自己的代码,有挺多值得注意的点】
bug
- 刚开始没考虑n=1的情况
- 在大于开方数的质因数的添加情况下忘记计数了
代码
#include<iostream>
#include<math.h>
#include<vector>
using namespace std;
typedef long long LL;
struct Factor {//因数结构:记录素数因数本身和它出现的次数
LL prime, cnt = 0;
};
bool isPrime(LL num) {//判断是否是素数
if (num <= 1) return false;
for (LL i = 2; i <= (LL)sqrt(num*1.0); i++) {//这里一定要写出<=,不然25会被当成素数
if (num%i == 0) return false;
}
return true;
}
int main()
{
LL n;
cin >> n;
if (n == 1) {//有一个测试点专门测试为1的情况,如果不考虑则过不了
printf("1=1");
return 0;
}
LL fcnt = 0, num = 2, temp = n;
vector<Factor> factor;
while (num <= (LL)sqrt(1.0*n)) {//找出数n可能的素数因数,必然<=n的开方,如有大于的也只有一个
if (isPrime(num)) {
Factor f;
f.prime = num;
factor.push_back(f);
fcnt++;
}
num++;
}
for (LL i = 0; i < fcnt; i++) {//确认各素数是否是数n的因数,如果是求出个数
while (n%factor[i].prime == 0) {
factor[i].cnt++;
n /= factor[i].prime;
}
if (n == 1) break;//当所有因数都被找到了就不再找了(这句话可以节省一点时间
}
if (n != 1) {//如果n没有被<=sqrt(n)的因数除尽,那么就说明还有一个大于其开方的因数
Factor f;
f.prime = n;
f.cnt++;
factor.push_back(f);//把该因数计一次加入因数列
}
bool iseverprit = false;//用于判断是否要输出'*'
printf("%lld=", temp);
for (LL i = 0; i < factor.size(); i++) {
if (factor[i].cnt == 0) continue;
else {
if (iseverprit) printf("*");
printf("%lld", factor[i].prime);
if (factor[i].cnt > 1) printf("^%lld", factor[i].cnt);
iseverprit = true;
}
}
return 0;
}
dalao的代码
全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~
借鉴点
- 不要把循环体内会发生改变的值放在判断条件里,为了避免这个发生,以后涉及sqrt(n)的操作都用另外一个变量来存储
- 在找因数循环体内,n被除尽为1时就可以break,这样可以节省一丢时间
if (n == 1) break;//当所有因数都被找到了就不再找了(这句话可以节省一点时间
- emmm本题看晴神的实战代码就好,如果有不理解可以去看对应篇章的笔记