2020牛客寒假算法基础集训营3 H 牛牛的k合因子数

刚开始把题意理解错了

先埃筛筛出合数,再算出1~n的合因子数 其实直接开个数组记录相同合因子数的个数就行了(ans[num[i]]++)

也就是桶排序 

没必要先sort排序,再统计各合因子数的个数 而当时为了O(n)统计 不得不按合因子个数从小到大依次计算 也就是先找到该合因子个数的起点 再找到终点 

其实也可以两次二分找该合因子个数的起点和终点

找起点时判定条件为mid<k 此时l为起点

找终点时判定条件为mid≤k 此时r为终点

两次二分结束l=r+1

注意:埃筛复杂度nlog(log n)

#include<bits/stdc++.h>//两次二分找 
#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<<num[i]<<endl;
     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]<i&&s<=n)s++;
        //cout<<i<<' '<<s<<endl;
        ans[i]-=s;
        while(num[s]==i&&s<=n)s++;
            //cout<<i<<' '<<s<<endl;
        ans[i]+=s;
        //while(num[s]<i&&s)s--;
    }
    
    for(int i=1;i<=m;i++){
        int k;
        cin>>k;
        if(k>num[n])cout<<0<<endl;
        else cout<<ans[k]<<endl;
    }
    return 0;
} 

std

#include<bits/stdc++.h>
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]);
    }
}

猜你喜欢

转载自www.cnblogs.com/wyh447154317/p/12285771.html