结合网上的各位老师的思想提炼总结~欢迎大家交流学习~
文章目录
- 求最大公约数
- 试除法求约数
- 求约数个数
- 求约数之和
- 注意
一、求最大公约数
1.什么是最大公约数?多个整数的共有约数中的最大约数,记作gcd(a,b)吧
2.怎么求最大公约数?求最大公约数有很多方法,今天来分享一下其中的辗转相减法和辗转相除法。用gcd(a,b)来表示a和b的最大公约数,则gcd(a,b)=gcd(a,ka+b)(a,b,k都是自然数)。理由如下,如果p是a和ka+b的公约数,说明p是a的约数,要想p也是ka+b的约数,则p也得是b的约数,所以p是a和b的公约数,因此他们的最大公约数也相等。
比如:gcd(78,14)=gcd(64,14)=gcd(50,14)=gcd(36,14)=gcd(22,14)=gcd(8,14)=gcd(8,6)=gcd(2,6)=gcd(2,4)=gcd(2,2)=gcd(0,2)=2 但迭代相减法步数比较多,因此可以gcd(78,14)=gcd(14*5+8,14)=gcd(8,14)=gcd(8,8*1+6)=gcd(8,6)=gcd(6*1+2,6)=gcd(2,6)=gcd(2,2*1+4)=gcd(2,4)=gcd(2,2*1+2)=gcd(2,2)=gcd(2,2*1+0)=gcd(2,0),由此得到迭代相除法gcd(a,b)=gcd(a%b,b)=gcd(b,a%b)
3.core idea:对(a,b)连续使用辗转相除,直到括号右边数字为0,括号左边即是两数最大公约数
4.代码如下:
//小括号左边放除数,右边放约数
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
//辗转相除,直到小括号内右边数为0,小括号内左边数为最大公约数
二、试除法求约数
1.什么是约数?a%b==0,则b是a 的约数
2.core idea:枚举[1,],如果x%i==0,则说明i是x的约数,需要存储进数组。那另一个约数x/i(x/i!=i)也需要存储进数组。
3.代码如下:
vector<int> get_divisors(int x)
{
vector<int> res;//存储x的约数的数组
for (int i = 1; i*i<=x; i ++ )
if (x % i == 0)
{
res.push_back(i);
if (i != x / i) res.push_back(x / i);
}
sort(res.begin(), res.end());//对x的约数们排序
return res;
}
三、 求约数个数
1.
约数个数=
比如分解质因子,12的质因子有2,3。12的约数有1,2,3,4,12这六个。
因此2可以取0/1/2个,3可以取0/1个,再组合成6种情况。
2.core idea:先找到x的所有质因数和每个质因数的个数并存储起来(分解质因数 ),再套用红字公式
3.代码如下:
typedef long long LL;
const int mod = 1e9 + 7;
unordered_map<int, int> a;//{p,e} p为x的某个质因数,用.first表示 e为某个质因数p的个数,用.second表示
void decompose(int x)//分解x的质因数
{
for(int i=2;i*i<=x;i++)
{
while(x%i==0)a[i]++,x/=i;
}
if(x>1)a[x]++;//x>1,说明这就是那个大于根下x的质因子
}
---------------------------------------------------------------
LL res=1;//约数个数,初始化为1用于累乘
for(auto m:a){res=res*(m.second+1)%mod;}//取模是为了防止结果溢出,通常在处理大数时使用
cout<<res;
四、求约数之和
1.
x的约数之和=(x的每个质因子的约数之和)的乘积,其中(x的每个质因子的约数之和)用等差数列求和
2..core idea:先找到x的所有质因数和每个质因数的个数并存储起来(分解质因数 ),再套用红字公式
3.代码如下:
typedef long long LL;
const int mod = 1e9 + 7;
unordered_map<int, int> a;//a[i]为第i个{p,e} p为x的某个质因数,用.first表示 e为某个质因数p的个数,用.second表示
void decompose(int x)//分解x的质因数
{
for(int i=2;i*i<=x;i++)
{
while(x%i==0)a[i]++,x/=i;
}
if(x>1)a[x]++;//x>1,说明这就是那个大于根下x的质因子
}
---------------------------------------------------------------
LL res=1;//x的约数之和,初始化为1用于累乘
for(auto m:a){
LL fir=m.first,sec=m.second;
LL t=1;//x的每个质因数的约数之和,初始化为1用于累加
while(sec--)//模拟求和等比数列
{
t=(t*fir+1)%mod;
res=res*t%mod;
}
}//取模是为了防止结果溢出,通常在处理大数时使用
cout<<res;
注意
如果以上有未提到的概念或疑惑,可以看我之前的文章有细讲的~比如分解x的质因数这一部分