约数的基本知识

一.基本知识

若b能整除a,则b为a的因子,且记b|a

1.如何求n的约数集合和约数数量???

方法1:试除法

试除即可,到n1/2

void solve(int n=100){
    
    
	for(int i=1;i*i<=n;i++){
    
    
		if(n%i==0){
    
    
			p[++cnt]=i;
			if(i*i!=n)p[++cnt]=n/i;
		} 
	}
}

方法2:唯一分解定理

方法介绍如下:
根据唯一分解定义:N=p1a1p2a2……ptat
则N的约数为:p1c1p2c2……ptct(0<=ci<=ai)
易知:约数数量=mul(ai+1)(1<=i<=t)

void solve(int n){
    
    
	for(int i=2;i*i<=n;i++){
    
    
		if(n%i==0){
    
    
			p[++cnt]=i;
			while(n%i==0)a[cnt]++,n/=i;
		}
	}
	if(n>1)p[++cnt]=n,a[cnt]=1;
	
	long long ans=1;
	for(int i=1;i<=cnt;i++)ans*=(a[i]+1);
	
	long long sum=1,add;
	for(int i=1;i<=cnt;i++){
    
    
	    add=0;
		for(int j=0;j<=a[i];j++)add=add*p[i]+1;
		sum*=add;
	}
}

2.如何求1-n的每个数的约数集合?

试除法O(n3/2),out
方法介绍如下:
对于每个数d,以d为约数的数就是d,2d,3d……,n/d *d
O(N+N/2+N/3+……+N/N)=O(NlogN)
推论:1-n每个数的约数个数和约为nlogn

vector<int>f[100005];
void solve(int n){
    
    
	for(int i=1;i<=n;i++){
    
    
		for(int j=i;j<=n;j+=i){
    
    
			f[j].push_back(i); 
		}
	}
	for(int i=1;i<=n;i++){
    
    
		for(int j=0;j<f[i].size();j++){
    
    
			cout<<f[i][j]<<" ";
		}
		cout<<endl;
	}
}

二.开始刷题

例题1

题目描述:
给定自然数n,求一个最大A(1<=A<=n),满足比A小的数的约数数量均小于A的约数数量

题解:
唯一分解定理:N=p1a1p2a2……ptat
约数数量:mul(ai+1)(1<=i<=t)
用dfs枚举每个质因子的数量,求mul即可

#include<bits/stdc++.h>
using namespace std;
int a[20]={
    
    0,2,3,5,7,11,13,17,19,23,29,31,37,41};//越多越准确 
long long n,ans=0,maxx=0; 

void dfs(long long now,long long sum,int cnt){
    
    
	if(sum>maxx){
    
    
		maxx=sum,ans=now;
	}
	else if(sum==maxx)ans=min(ans,now); //处理答案 
	if(cnt==13)return; 
	long long k=1;
	for(int i=1;i;i++){
    
    
		k=k*a[cnt];
		if(k*now>n)return;
		dfs(now*k,sum*(i+1),cnt+1);//第cnt个质数要i个 
	}
}
int main(){
    
    
	cin>>n;
	dfs(1,1,1);
	cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43602607/article/details/110437954
今日推荐