程序实践--数论之约数

讲解:第四章 数学知识(一) - AcWing 

一、试除法求一个数的所有约数

约数一定是成对出现,所以枚举范围也可以优化

#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()); 
//因为我们在存入res的时候是一对一对地存入的,所以最后用sort排序一下
	return res;
}


int main()
{
	int n=0;
	cin>>n;
	while(n--)
	{
		int ai=0;
		cin>>ai;
		auto res=get_divisors(ai);
		for(auto t:res)
			cout<<t<<' ';
		cout<<endl;
	}
	return 0;
}

二、约数个数

讲解: AcWing 870. 约数个数 - AcWing

·两个公式:

//两个公式首先都得先分解质因数

//两个公式都是累乘的结果

难点:已经知道分解质因数的结果了,如何用代码实现这两个公式的结果

--------代码实现的时候就每一次算新的一个因式,然后用res=res*最新的因式算最后的结果 

·题目: 

 

 思路分析:

·对于给定的n个数,先求n个数的乘积的分解质因数的结果

·怎么求多个数乘积的分解质因数的结果: 对每个数都分解质因数,然后把指数累加在一起就好了

可以用unordered_map(哈希表)来存结果------unordered_map[pi]+=ai;

//重要思想:用数组下标存数,用元素的值存这个数的个数!!!

·然后再利用公式约数个数

#include <iostream>
#include <algorithm>
#include <cstring>
#include <unordered_map>

using namespace std;

typedef long long LL;

const int N=110;
const int mod=1e9+7;

int main()
{
	int n;
	cin>>n;
	unordered_map<int,int> primes; //存储a的质因数和个数
	
	while(n--)
	{
		int a;
		cin>>a;
        //这里用了“分解质因数”的代码知识
		for(int i=2;i<=a/i;i++)  //每个a都分解 所有a相乘的结果便得到了 
		{
			while(a%i==0) 
			{
				a/=i;
				primes[i]++; 
			}
		}
		if(a>1)
			primes[a]++;
		
	}
	//此时,哈希表primes里面就存储了所有的质因数 和 每个质因数的个数
	LL res=1;
	for(auto p:primes)//枚举所有的质因数
	{
		res=res*(p.second+1)%mod; 
		//代码实现的时候就每一次算新的一个因式,然后用res=res*最新的因式算最后的结果 
	}
	cout<<res<<endl;
	return 0;
}

三、约数之和

讲解:AcWing 871. 约数之和 - AcWing 

·公式

见上面的公式图片

·思路注意点:

代码实现约数之和的公式的时候,每一次算新的一个因式,然后用res=res*最新的因式算最后的结果。只不过每个新的因式不再是一步直接求得,也是要用小循环把每个和累加起来

#include <iostream>
#include <algorithm>
#include <cstring>
#include <unordered_map>

using namespace std;

typedef long long LL;

const int N=110;
const int mod=1e9+7;

int main()
{
	int n;
	cin>>n;
	unordered_map<int,int> primes; //存储a的质因数和个数
	
	while(n--)
	{
		int a;
		cin>>a;
		for(int i=2;i<=a/i;i++)  //每个a都分解 所有a相乘的结果便得到了 
		{
			while(a%i==0) 
			{
				a/=i;
				primes[i]++; 
			}
		}
		if(a>1)
			primes[a]++;
		
	}
	//此时,哈希表primes里面就存储了所有的质因数 和 每个质因数的个数
	LL res=1;
	for(auto p:primes)//枚举所有的质因数
	{
		LL t=1;
		LL b=p.second;
		while(b--)
		{
			t=(t*p.first+1)%mod;//这样子t便是每一个新的因式(这里要反应过来)
		}
		res=res*t%mod; 
		//代码实现的时候就每一次算新的一个因式,然后用res=res*最新的因式算最后的结果 
	}
	cout<<res<<endl;
	return 0;
}

 //说明:二和三的题目都涉及到了取模,代码实现的时候注意取模的处理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值