约数知识总结

约数相关知识

最大公约数

欧几里得算法(辗转相除法

核心思想: GCD(a, b)<=> GCD(b, a % b)
证明: 略
结束条件: GCD(a, 0) 是 a

#include <iostream>
using namespace std;
//辗转相除法求最大公约数
// (a,b) <=> (b, a % b)
// LOG(N)

int gcd(int a, int b)
{
	return b ? gcd(b, a % b) : a;
}
int main()
{
	int n;
	scanf("%d", &n);
	while(n --)
	{
		int a, b;
		scanf("%d%d", &a,&b);
		printf("%d\n",gcd(a,b));
	}

  return 0;
}

约数总个数

相关知识点: 一个整数具有唯一形式的质因数分解式
N 可表示为 p1^c1 * p2^c2 * … *pk^ck
约数个数: (c1 + 1) * (c2 + 1) * … * (ck + 1)

例题

给定 n 个正整数 ai,请你输出这些数的乘积的约数个数,答案对 10^9+7
取模。

输入格式

第一行包含整数 n。

接下来 n行,每行包含一个整数 ai

输出格式

输出一个整数,表示所给正整数的乘积的约数个数,答案需取模。

数据范围
1≤n≤100,1≤ai≤2×10^9

输入样例:
3
2
6
8
输出样例:
12

#include <iostream>
#include <algorithm>
#include <unordered_map>
//equal hash table
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;

int main()
{
  int n;
  cin >> n;
  
  unordered_map<int ,int > primes;
  while(n --)
  {
  	int x;
  	cin >> x;
  	
  	for(int i =2 ; i <= x / i; i++)
  	  while(x % i == 0)
  	   {
  	   	
  	   	 x /= i;
  	   	 primes[i] ++;
	   }
	if(x > 1) primes[x] ++;
  }
  
  LL res = 1;
  for(auto prime : primes)
    res = res * (prime.second + 1) % mod;
  cout << res << endl;

  return 0;
}

所有约数和

约数总和公式:
( p1^0 + p1^1 +…+ p1^c1) mul…mul (pk^0 + pk^1 +…+ pk^ck)

例题

给定 n 个正整数 ai,请你输出这些数的乘积的约数之和,答案对 10^9+7取模。

输入格式
第一行包含整数 n

接下来 n行,每行包含一个整数 ai

输出格式
输出一个整数,表示所给正整数的乘积的约数之和,答案需对 10^9+7
取模。

数据范围
1≤n≤100,1≤ai≤2×10^9

输入样例:
3
2
6
8

输出样例:
252

#include <iostream>
#include <algorithm>
#include <unordered_map>
//equal hash table
//求约数和 
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;

int main()
{
  int n;
  cin >> n;
  
  unordered_map<int ,int > primes;
  while(n --)
  {
  	int x;
  	cin >> x;
  	
  	for(int i =2 ; i <= x / i; i++)
  	  while(x % i == 0)
  	   {
  	   	
  	   	 x /= i;
  	   	 primes[i] ++;
	   }
	if(x > 1) primes[x] ++;
  }
  
  LL ans = 1;
  for(auto prime : primes)
  { 
     int p = prime.first;
     int a = prime.second;//index
     LL t = 1;
     //约数和公式 
     while(a --) t = (t * p + 1) % mod;
     
     ans = (ans * t) % mod;
     
  } 
  cout << ans << endl;

  return 0;
}

试除法求所有约数

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

vector<int> get_divisors(int n)
{
	vector<int> res;
	
	for(int i = 1; i <= n / i; 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;
}

int main()
{
	int n;
	cin >> n;
	while(n --)
	{
		int x;
		cin >> x;
		auto res = get_divisors(x);//get 约数 
		for(auto t : res) cout << t << ' ';
		cout << endl;
	}

  return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值