文章目录
Contest100000592 - 《算法笔记》5.5小节——数学问题->质因子分解
5.5小节——数学问题->质因子分解
质因子分解代码
//质因子分解
struct factor
{
int x,,cnt;//x为质因子,cnt为其个数
}fac[10];
//枚举1~sqrt(n)范围内的所有质因子p,判断p是否为n的因子
if(n % prime[i] == 0)//若果prime[i]是n的因子
{
fac[num].x = prime[i];//记录该因子
fac[num].cnt = 0;
while(n % prime[i] == 0)//计算出质因子prime[i]的个数
{
fac[num].cnt++;
n /= prime[i];
}
num++;//不同质因子个数加一
}
if(n != 1)//如果无法被根号n以内的质因子除尽
{
fac[num].x = n;//那么一定有一个大于根号n的质因子
fac[num++].cnt = 1;
}
例题PAT-A-1059-Prime-Factors
题目链接:
https://pintia.cn/problem-sets/994805342720868352/problems/994805415005503488
//例题PAT-A-1059-Prime-Factors
#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
const int maxn = 100010;
bool is_prime(int n)//判断n是否为素数
{
if(n==1) return false;
int sqr = (int)sqrt(1.0*n);
for(int i=2;i<=sqr;i++)
{
if(n%i==0)
return false;
}
return true;
}
int prime[maxn],pNum = 0;
void Find_Prime()//求素数表
{
for(int i=1;i<maxn;i++)
{
if(is_prime(i) == true)
prime[pNum++] = i;
}
}
struct factor
{
int x,cnt;//x为质因数,cnt为其个数
}fac[10];
int main()
{
Find_Prime();
int n,num=0;//num为n的不同的质因子个数
scanf("%d",&n);
// cin>>n;
if(n == 1)
printf("1=1");
// cout<<"1=1";
else
{
printf("%d=",n);
// cout<<n<<"=";
int sqr = (int)sqrt(1.0*n);//n的根号
//枚举根号n以内的质因子
for(int i=0;i<pNum && prime[i] <= sqr;i++)
{
if(n % prime[i] == 0)//如果prime[i]是n的质因子
{
fac[num].x = prime[i];//记录该因子
fac[num].cnt = 0;
while(n % prime[i] == 0)//计算出质因子的个数
{
fac[num].cnt++;
n /= prime[i];
}
num++;//不同质因子个数加一
}
if(n == 1) break;//及时退出循环节省时间
}
if(n != 1)//如果无法被根号n以内的质因子除尽
{
fac[num].x = n;//那么一定有 一个 大于根号n的质因子
fac[num++].cnt = 1;
}
//按格式输出结果
for(int i=0;i<num;i++)
{
if(i>0) cout<<"*";
cout<<fac[i].x;
if(fac[i].cnt > 1)
{
cout<<"^"<<fac[i].cnt;
}
}
}
return 0;
}
Codeup习题
Codeup习题-Contest100000592 - 《算法笔记》5.5小节——数学问题->质因子分解
题目链接:http://codeup.cn/contest.php?cid=100000592
1783-Problem-A-完数
题目链接:http://codeup.cn/problem.php?cid=100000592&pid=0
//1783-Problem-A-完数
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
bool isFull(int num)
{
int sum = 0;
// int sqr = (int)sqrt(1.0*n);
// for(int i=2;i<=sqr;i++)
//此处不能用sqrt(),原因不明
for(int i=1;i<num;i++)
{
if(num % i == 0)
{
sum+=i;
}
}
return sum==num;
}
int main()
{
int n;
while(cin>>n)
{
bool flag = false;
for(int i=2;i<=n;i++)
{
if(isFull(i))
{
if(flag)
cout<<" ";
cout<<i;
flag = true;
}
}
cout<<endl;
}
return 0;
}
1783-Problem-B-完数(同上题)
题目链接: http://codeup.cn/problem.php?cid=100000592&pid=1
1947-Problem-C-质因数的个数
题目链接:http://codeup.cn/problem.php?cid=100000592&pid=2
//1947-Problem-C-质因数的个数
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 100010;
/*书上的方法不知道咋运行错误,在DEVC++上还好好的
bool is_prime(int n)//判断n是否为素数
{
if(n==1) return false;
int sqr = (int)sqrt(1.0*n);
for(int i=2;i<=sqr;i++)
{
if(n%i==0)
return false;
}
return true;
}
int prime[maxn],pNum = 0;
void Find_Prime()//求素数表
{
for(int i=1;i<maxn;i++)
{
if(is_prime(i) == true)
prime[pNum++] = i;
}
}
struct factor
{
int x,cnt;//x为质因数,cnt为其个数
}fac[10];
int main()
{
Find_Prime();
int n,num=0;//num为n的不同的质因子个数
while(cin>>n)
{
memset(fac,0,sizeof(fac)*100);
int result = 0;
if(n == 1)
cout<<"1=1";
else
{
int sqr = (int)sqrt(1.0*n);//n的根号
//枚举根号n以内的质因子
for(int i=0;i<pNum && prime[i] <= sqr;i++)
{
if(n % prime[i] == 0)//如果prime[i]是n的质因子
{
fac[num].x = prime[i];//记录该因子
fac[num].cnt = 0;
while(n % prime[i] == 0)//计算出质因子的个数
{
fac[num].cnt++;
n /= prime[i];
}
num++;//不同质因子个数加一
}
if(n == 1) break;//及时退出循环节省时间
}
if(n != 1)//如果无法被根号n以内的质因子除尽
{
fac[num].x = n;//那么一定有 一个 大于根号n的质因子
fac[num++].cnt = 1;
}
//按格式输出结果
for(int i=0;i<num;i++)
{
result += fac[i].cnt;
}
cout<<result<<endl;
}
}
return 0;
}
*/
int main()
{
int n;
while(cin>>n)
{
int num = 0;
for(int i=2;i<=sqrt(1.0*n);i++)
{
while(n % i == 0)
{
n /= i;
num++;
}
}
if(n!=1)
num++;
cout<<num<<endl;
}
return 0;
}
1948-Problem-D-约数的个数
题目链接:http://codeup.cn/problem.php?cid=100000592&pid=3
此题有时间限制的大坑:包括常规判断质数超时和使用cin和cout超时(应用printf)
还有一点:约数和定理:
约数和定理:
对于一个大于1正整数n可以分解质因数:n=p1a1*p2a2*p3a3*…*pkak,
则由约数个数定理可知n的正约数有(a₁+1)(a₂+1)(a₃+1)…(ak+1)个,
那么n的(a₁+1)(a₂+1)(a₃+1)…(ak+1)个正约数的和为
f(n)=(p10+p11+p12+…p1a1)(p20+p21+p22+…p2a2)…(pk0+pk1+pk2+…pkak)
//1948-Problem-D-约数的个数
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 100010;
struct factor
{
int x,cnt;//x为质因数,cnt为其个数
}fac[10];
int prime[maxn],pNum=0;
bool p[maxn] = {false};
void Find_Prime()//素数筛
{
for(int i=2;i<maxn;i++)
{
if(!p[i])
{
prime[pNum++]=i;
for(int j = i+i;j < maxn;j += i)
p[j] = true;
}
}
}
int main()
{
Find_Prime();
int N;
while(scanf("%d",&N) && N)
{
while(N--)
{
int n;//输入n个整数
scanf("%d", &n);
int num = 0;
//枚举根号n以内的质因子
for(int i=0;i<pNum && prime[i] <= sqrt(1.0*n);i++)
{
if(n % prime[i] == 0)//如果prime[i]是n的质因子
{
fac[num].x = prime[i];//记录该因子
fac[num].cnt = 0;
while(n % prime[i] == 0)//计算出质因子的个数
{
fac[num].cnt++;
n /= prime[i];
}
num++;//不同质因子个数加一
}
if(n == 1) break;//及时退出循环节省时间
}
if(n != 1)//如果无法被根号n以内的质因子除尽
{
fac[num].x = n;//那么一定有 一个 大于根号n的质因子
fac[num++].cnt = 1;
}
int facnum = 1;
for(int i=0;i<num;i++)
{//累乘所有质因数的个数+1
facnum *= fac[i].cnt + 1;
}
printf("%d\n",facnum);
}
}
return 0;
}
1997-Problem-E-完数与盈数
题目链接: http://codeup.cn/problem.php?cid=100000592&pid=4
//1997-Problem-E-完数与盈数
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 100010;
//一个数如果恰好等于它的各因子(该数本身除外)子和
//1既不是质数也不是合数,用质因子素数打表不合适
int sum(int num)//求数的除1外各因子之和
{
int sum = 0;
for(int i=1;i<num;i++)
{
if(num % i == 0)
sum+=i;
}
return sum;
}
int main()
{
cout<<"E:";
for(int i=2;i<=60;i++)
{
if(sum(i) == i)
cout<<" "<<i;
}
cout<<endl;
cout<<"G:";
for(int i=2;i<=60;i++)
{
if(sum(i) > i)
cout<<" "<<i;
}
cout<<endl;
return 0;
}
总结
质因子分解就是将合数分解为素数之积(5.4节为素数),要注意灵活运用;
注意时间限制、约数和定理