求一个数的所有因子(约数)

约数是指若整数a除以整数b(b≠0)除得的商正好是整数而没有余数,比如10的约数分别为1,2,5,10,这些数都能被10整除而没有余数,所以他们都是10的约数。

下面我们来看看约数如何求解

1.传统方法思路:1-a遍历

思路:从1-a遍历,只要这个数能被a整除,那么就把这个数记录起来

int fac[100],t=0;
void get_fac(int a){
	for(int i=1; i<=a; i++){
		if(a%i==0){			//如果i能被a整除,那么这个数就是a的因数 
			fac[t++]=i; 	//将所有的因数存储起来,其中fac[t++]相当于fac[t]=i;t++; 
		}
	}
} 

完整代码

#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#include <cmath>
using namespace std;
int n;
int fac[100],t=0;			//将所有因数存储起来 
/*求一个数的所有因数*/
void get_fac(int a){
	for(int i=1; i<=a; i++){
		if(a%i==0){			//如果i能被a整除,那么这个数就是a的因数 
			fac[t++]=i; 	//将所有的因数存储起来,其中fac[t++]相当于fac[t]=i;t++; 
		}
	}
} 
int main(){
    cin>>n;
    
    get_fac(n);
    
    for(int i=0; i<t; i++){
    	cout<<fac[i]<<" ";
    }
	return 0;
} 

输出结果

2.1-根号n遍历

如果我们用上面这种方法,数据量一大就承受不了,我们必须找到更快的方法。例如下面这种,它将问题规模缩减至根号n

思路:如果一个整数能被根号n前的数整除,那么根号后面一定存在大于根号n的一个数能被n整除,这个数是b(b=n/i)。比如数字45,开根后范围大概是1-3*根号n(1-5)。遍历1-5,

其中能被45整除的有1,3,5。

45被1整除,那么根号后面的45(=45/1)也能被整除;

45被3整除,那么根号后面的15(=45/3)也能被整除;

45被5整除,那么根号后面的9(=45/5)也能被整除;

故45所有的因子有:1,3,5,9,15,45。

int n;
int fac[100],t=0;
void get_fac(int n){
	for(int i=1; i<=sqrt(n); i++){
		//根号前 
		if(n%i==0){			
			fac[t++]=i;		
            //根号后
			if(n/i != i){		 
				fac[t++]=n/i;	 
			}
		}
	}
}

完整代码

#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#include <cmath>
using namespace std;


/*求一个数的所有因数*/
int n;
int fac[100],t=0;
void get_fac(int n){
	for(int i=1; i<=sqrt(n); i++){
		//根号前 
		if(n%i==0){			
			fac[t++]=i;		//i能被n除尽,所以i是n的因子 
			//根号后----在满足能被根号前整除才能根号后的判断				
			if(n/i != i){		//如果有一个数能被i整除,那么大于根号的一定有一个数也能被整除,这个数是b=n/i 
				fac[t++]=n/i;	//但是这个数可能会相同,比如9=3*3,那么我们加一个限制条件,如果n/i不等于i才添加因数,因为如果n/i==i时在根号前已经被添加过一次因数了,不信自己试试9的推导? 
			}
		}
		
	}
} 
int main(){
	
    cin>>n;
	
	get_fac(n);
	/*输出*/ 
	for(int i=0; i<t; i++){
		cout<<fac[i]<<" ";
	}
	return 0;
} 

输出结果

3.进阶写法:set集合存储不相同元素

当然,如果你学过c++的set集合,你还可以这样写

void get_fac(int x){
	for(int i=1; i<=sqrt(n); i++){
		if(n%i==0){
			fac.insert(i);
			fac.insert(n/i);
		}
	}
}

set集合是一个内部有序且不含重复元素的容器,它可以通过引入头文件#include<set>使用,

它只能通过迭代器iterator访问,通过*it进行访问

#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#include <cmath>
#include <set>
using namespace std;


int n;
set<int> fac;


void get_fac(int x){
	for(int i=1; i<=sqrt(n); i++){
		if(n%i==0){
			fac.insert(i);        //set集合插入根号前一个元素
			fac.insert(n/i);      //set集合插入根号后一个元素
		}
	}
}
int main(){
	cin>>n;
	
	get_fac(n);
	
    //输出
    /*
    *  set<int>::iterator it 获取迭代器it
    */
	for(set<int>::iterator it = fac.begin(); it!=fac.end(); it++){
		//printf("%d ",*it);
		cout<<*it<<" ";
	}


	return 0;
} 

输出结果

各位挑选喜欢的学习就好了。注意:如果是求大数,int换成long long类型就好了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值