目录
一、试除法求约数
给定 nn 个正整数 ai,对于每个整数 ai,请你按照从小到大的顺序输出它的所有约数。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个整数 ai。
输出格式
输出共 nn 行,其中第 i 行输出第 i 个整数 a 的所有约数。
数据范围
1≤n≤100,
2≤ai≤2×10 9
输入样例:
2
6
8
输出样例:
1 2 3 6
1 2 4 8
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
int n;
vector <int> get_divisorts(int n){ //求约数函数
vector <int> res; //用了存n的所有约数
for(int i = 1;i <= n / i;i ++){ //因为n的约数个数小于n / i
if(n % i == 0){ //如果可以整除
res.push_back(i); //把i压入vector
if(i != n / i) res.push_back(n / i); //如果n不是i的平方,那n / i就是一个新的约数,把n / i压入vector
}
}
sort(res.begin(),res.end()); //因为题目要求约数要从小到大排序,所以在最后需要排一次需
return res; //返回这个数的所有约数
}
int main(){
scanf("%d",&n); //需要求约数的数的个数
while(n --){
int x; //需要求约数的数
scanf("%d",&x); //读入
auto res = get_divisorts(x);
//大概的讲一下auto,用来定义变量时,它表示让计算机来猜这个数的类型,在这里就表示vector <int>
for(auto i : res) printf("%d ",i);
//这里的for循环表示遍历res数组,i是遍历到的哪一位的数字
printf("\n"); //记得要输出回车哦
}
return 0;
}
二、 约数个数
给定 n 个正整数 ai,请你输出这些数的乘积的约数个数,答案对 109+7 取模。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个整数 ai。
输出格式
输出一个整数,表示所给正整数的乘积的约数个数,答案需对 109+7 取模。
数据范围
1≤n≤100,
1≤ai≤2×109
输入样例:
3
2
6
8
输出样例:
12
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int main()
{
int n;
cin>>n;
unordered_map<int,int> prime;
while(n--)
{
int x;
cin>>x;
for(int i=2;i<=x/i;i++)
{
while(x%i==0)
{
x/=i;
prime[i]++;
}
}
if(x>1)
prime[x]++;
}
ll res=1;
for(auto p : prime)
res=res*(p.second+1)%mod;
cout<<res<<endl;
return 0;
}
三、约数之和
给定 n 个正整数 ai,请你输出这些数的乘积的约数之和,答案对 109+7 取模。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个整数 ai。
输出格式
输出一个整数,表示所给正整数的乘积的约数之和,答案需对 109+7 取模。
数据范围
1≤n≤100,
1≤ai≤2×109
输入样例:
3
2
6
8
输出样例:
252
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int main()
{
int n;
cin>>n;
unordered_map<int,int> prime;
while(n--)
{
int x;
cin>>x;
for(int i=2;i<=x/i;i++)
{
while(x%i==0)
{
x/=i;
prime[i]++;
}
}
if(x>1)
prime[x]++;
}
ll res=1;
for(auto p : prime)
{
int f=p.first,s=p.second;
ll t=1;
while(s--)
t=(t * f + 1) % mod;
res=res * t % mod;
}
cout<<res<<endl;
return 0;
}
四、求最大公约数(欧几里得算法(辗转相除法))
1、普通做法(记)
#include<bits/stdc++.h>
using namespace std;
/*
求两个正整数 a 和 b 的 最大公约数 d
则有 gcd(a,b) = gcd(b,a%b)
证明:
设a%b = a - k*b 其中k = a/b(向下取整)
若d是(a,b)的公约数 则知 d|a 且 d|b 则易知 d|a-k*b 故d也是(b,a%b) 的公约数
若d是(b,a%b)的公约数 则知 d|b 且 d|a-k*b 则 d|a-k*b+k*b = d|a 故而d|b 故而 d也是(a,b)的公约数
因此(a,b)的公约数集合和(b,a%b)的公约数集合相同 所以他们的最大公约数也相同 证毕#
*/
int gcd(int a, int b){
return b ? gcd(b,a%b):a;
}
int main(){
int n,a,b;
cin>>n;
while(n--) cin>>a>>b,cout<<gcd(a,b)<<endl;
return 0;
}
2、STL做法(__gcd())
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,a,b;
cin>>n;
while(n--) cin>>a>>b,cout<<__gcd(a,b)<<endl;
return 0;
}