刚开始把题意理解错了
先埃筛筛出合数,再算出1~n的合因子数 其实直接开个数组记录相同合因子数的个数就行了(ans[num[i]]++)
也就是桶排序
没必要先sort排序,再统计各合因子数的个数 而当时为了O(n)统计 不得不按合因子个数从小到大依次计算 也就是先找到该合因子个数的起点 再找到终点
其实也可以两次二分找该合因子个数的起点和终点
找起点时判定条件为mid
找终点时判定条件为mid≤k 此时r为终点
两次二分结束l=r+1
注意:埃筛复杂度nlog(log n)
#include//两次二分找
#define ll long long
using namespace std;
const int N=1e5+5;
int vis[N],num[N],ans[N];
int main(){
int n,m;
cin>>n>>m;
for(int i=2;i<=n;i++){
if(vis[i])continue;
for(int j=i;j<=n/i;j++)vis[i*j]=1;
}
for(int i=2;i<=n;i++)
for(int j=1;j<=sqrt(i);j++){
if(vis[j]&&i%j==0)num[i]++;
int x=i/j;
if(x*j==i&&vis[x]&&i%x==0&&j!=x)num[i]++;
}
sort(num+1,num+1+n);
//for(int i=1;i<=n;i++)cout<
int s=0;
// for(int i=1;i<=n;i++)
// if(!pos[num[i]])pos[num[i]]=i;
for(int i=1;i<=num[n];i++){
while(num[s];
//cout<
ans[i]-=s;
while(num[s]==i&&s<=n)s++;
//cout<
ans[i]+=s;
//while(num[s]
}
for(int i=1;i<=m;i++){
int k;
cin>>k;
if(k>num[n])cout<<0<<endl;
else cout<endl;
}
return 0;
}
std
#include
using namespace std;
const int MAXN=100005;
int f[MAXN],cnt[MAXN],n,m,x;
bool prim[MAXN];
void init(int n)
{
for(int i=2;i<=n;++i)
{
prim[i]=true;
}
for(int i=2;i<=n;++i)
{
if(prim[i])
{
for(int j=i+i;j<=n;j+=i)
{
prim[j]=false;
}
}
else
{
for(int j=i;j<=n;j+=i)
{
cnt[j]++;
}
}
f[cnt[i]]++;
}
}
int main()
{
scanf("%d %d",&n,&m);
init(n);
while(m--)
{
scanf("%d",&x);
printf("%d\n",f[x]);
}
}