一.基本知识
若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;
}
}
二.开始刷题
题目描述:
给定自然数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;
}