约数问题(分解质因数、约数个数、约数之和、辗转相除)

概念

约数:也叫因数。若a%b==0,则称b是a的因数。

对于一个数N,可以构造N = p1^a1 + p2^a2 +...+ pn^an。

其中,p是底数,也必须是质因数,比如在分解12 = 2×2×3 = 2^2+3^1的式子中,2和3就是底数;a是指数,是底数出现的次数,比如2的指数是2,3的指数是1。

分解质因数

用一个unordered_map保存质因数,键是质因数的底数,值是质因数的指数,也就是底数出现的次数。

//对x进行质因数分解

unordered_map<int,int> m;  //注意头文件#include<unordered_map>
//键表示底数,值表示指数

for(int i=2; i<=x/i ;i++)
{
	while(x%i==0)
	{
		m[i]++;   //i的指数+1
		x/=i;
	}
}
if(x>1) m[x]++;   //x也是底数

约数个数

【定理】约数个数 = (a1+1) * (a2+1) * ... * (an+1)

例如12=2^2 + 3^1,约数是1,2,3,4,6,12,通过(2+1)*(1+1)得到约数个数为6。

//分解完质因数后保存在m(m是一个unordered_map)中

int ans=1;  //注意不能写0 
for(auto i:m)
{
	int a=i.first,b=i.second;  //键(first)是底数,值(second)是指数
	ans=ans*(b+1);
}
cout<<ans;

约数之和

定理】约数之和 = (p1^0+p1^1+...+p1^a1) * (p2^0+p2^1+...+p2^a2) * ... * (pn^0+pn^1+...+pn^an)。

例如12=2^2 + 3^1,约数之和为 (1+2+4) *(1+3) = 28。

//分解完质因数后保存在m(m是一个unordered_map)中
	
int ans=1;  //注意不能写0 
for(auto i:m)
{
	int a=i.first,b=i.second;

	int t=1;  //1是a^0 
	for(int j=1;j<=b;j++) t+=pow(a,j);

	ans=ans*t;
}
cout<<ans;

辗转相除法

辗转相除法,又称欧几里得算法,用来求两个数的最大公约数。

【定理】被除数与除数的最大公约数,就是除数与余数的最大公约数。

gcd(a, b) = gcd(b, a%b)。我们可以递归地实现这一步骤。

//返回a和b的最大公约数

int gcd(int a, int b)
{
	if (b == 0) return a;
	else return gcd(b, a % b);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值