数论基础知识
本篇文章主要讲述数论中基础算法 约数部分的内容
提示:本篇文章代码参考ACWing
!!:以下是本篇文章正文内容,下面案例可供参考
一、约数是什么?
约数,又叫因数。整数a除以整数b(b≠0) 除得的商正好是整数而没有余数,我们就说a能被b整除,或b能整除a。a称为b的倍数,b称为a的约数。
二、约数的相关算法
1.枚举出某一个数的所有约数
试除法:
d|n => n/d|n 枚举范围为1~n/d
时间复杂度:O(sqrt(n))
代码如下():
vector <int> get_divisors(int n)
{
vector<int> res;
for(int i=1;i<=n;i++){
if(n%i==0) res.push_back(i);
if(i!=n/i) res.push_back(n/i);
}
sort(res.begin(),res.end());
return res;
}
2.求约数的个数
由算数基本定理:\num(n) = p1^a1 * p2^a2*…pn*an.(p1,p2…为质数)
可知约数的个数由a1,a2…an的取法确定,每一个质数的指数的取法有(a+1)种取法,故
约数个数n=(a1+1)(a2+1)(a3+1)(a4+1)…(an+1)
代码如下(示例):
typedef long long ll;
const int mod=le9+7;
int main()
{
unodered_map <int,int> primes;
int n;
cin>>n;
while(n--){
cin>>a;
for(int i=1;i<n/i;i++){
while(a%i==0){
a=a/i;
primes[i]]++;
}
if(a>1) primes[a]++;
}
}
ll res = 1;
for(auto prime : primes) res = res * (prime.second +1)%mod;
cout<<res<<endl;
return 0;
}
3.最大公约数
欧几里得算法/辗转相除法
核心原理: d|n,d|m,则d|(n+m) 和d|xn+ym
即(a,b) = (b,a mod b)
三元运算符’ ? :'的用法 true执行:前的表达式,false执行后面的表达式
int gcd (int a,int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
int n;
cin>>n;
while(n--){
int a,b;
cin>>a>>b;
cout<<gcd(a,b)<<endl;
}
return 0;
}
}
4.约数之和
同样由算数基本定理:
\num(n) = p1^a1 * p2^a2 *… * .pn^an.(p1,p2…为质数)
参考求约数个数的算法,乘法分配得到:
typedef long long ll;
const int mod=le9+7;
int main()
{
unodered_map <int,int> primes;
int n;
cin>>n;
while(n--){
cin>>a;
for(int i=1;i<n/i;i++){
while(a%i==0){
a=a/i;
primes[i]]++;
}
if(a>1) primes[a]++;
}
}
ll res = 1;
for()
{
int p=primes.first;
int a=primes.second;
ll t=1;//总和
while(a--)
t=(t*p+1) % mod;
res = res*t % mod;
}
cout<<res<<endl;
return 0;
}
以上内容仅为提供思路,如有错误 欢迎指正!