三个问题
1,求最大公约数
2,约数个数的求解 ;
3,约数和的求解
一,求最大公约数
利用辗转相除法,有数学公式的,这里不再推导,直接上模板。
int gcd1(int a,int b){
return b?gcd1(b,a%b):a;
}
//上下两行代码等价
int gcd(int a,int b){
if(b)return gcd(b,a%b);
else return a;
}
该函数的返回值就是a,b的最大公约数,详细解释872. 最大公约数 - AcWing题库
例题
给定 n 对正整数 ai,bi,请你求出每对数的最大公约数。
输入格式
第一行包含整数 n。
接下来 n行,每行包含一个整数对 ai,bi。
输出格式
输出共 n行,每行输出一个整数对的最大公约数。
数据范围
1≤n≤105
1≤ai,bi≤2×109
输入样例:
2
3 6
4 6
输出样例:
3
2
代码实现
#include<iostream>
using namespace std;
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;
}
二,约数个数的求解
由算数基本定理: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)
具体实例
例题
给定 n个正整数 ai,请你输出这些数的乘积的约数个数,答案对 109+7 取模。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个整数 ai。
输出格式
输出一个整数,表示所给正整数的乘积的约数个数,答案需对 109+7109+7 取模。
数据范围
1≤n≤100
1≤ai≤2×109
输入样例:
3
2
6
8
输出样例:
12
代码实现(利用STL中的unordered_map记录指数次方数)
#include<iostream>
#include<unordered_map>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
int main(){
int n;
cin>>n;
unordered_map<int,int>s;
while(n--){
LL a;
cin>>a;
for(int i=2;i<=a/i;i++){
while(a%i==0){
s[i]++;
a/=i;
}
}
if(a>1)s[a]++;
}
LL ans=1;
for(auto i:s)ans=ans*(i.second+1)%mod;
cout<<ans<<endl;
return 0;
}
三,约数和的求解
和二基本相同,直接上题
给定 n个正整数 ai,请你输出这些数的乘积的约数之和,答案对 109+7 取模。
输入格式
第一行包含整数 n。
接下来 n行,每行包含一个整数 ai。
输出格式
输出一个整数,表示所给正整数的乘积的约数之和,答案需对 109+7109+7 取模。
数据范围
1≤n≤100
1≤ai≤2×109
输入样例:
3
2
6
8
输出样例:
252
代码实现
#include<iostream>
#include<unordered_map>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
int main(){
int n;
cin>>n;
unordered_map<int,int>s;
while(n--){
LL a;
cin>>a;
for(int i=2;i<=a/i;i++){
while(a%i==0){
s[i]++;
a/=i;
}
}
if(a>1)s[a]++;
}
LL ans=1;
for(auto i:s){
LL mid=1;
LL sum=1;
for(int j=1;j<=i.second;j++){
mid*=i.first;
mid%=mod;
sum+=mid;
sum%=mod;
}
ans=ans*sum%mod;
}
cout<<ans<<endl;
return 0;
}
详细题解在活动 - AcWing