H:牛牛的k合因子数(数论)

传送门

题意:

在这里插入图片描述

分析:

我写的有点麻烦…
先求1e5内的素数,然后就可以搞除1e5内的合数
然后就可以求1e5内每个数的合因子的个数
发现最大的合因子个数也不超过122
然后做个二维数组 p k [ i ] [ j ] pk[i][j] 存小于j且合因子个数为i的数的个数
访问的时候直接输出 p k [ k ] [ n ] pk[k][n] 即可
应该有更简单的写法,到时候会添加

代码:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <math.h>
#include <map>
#include <queue>
#include <set>
#define Pll make_pair
using namespace std;
typedef long long ll;
const int MAXN=1e5+50;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int phi=1e9+6;
int k;
int su[MAXN],c,b[MAXN];
bool a[MAXN];
int he[MAXN];
void prime()//素数筛
{
    memset(a,1,sizeof(a));
    a[0]=a[1]=0;
    c=1;
    for(int i=2;i<=MAXN;i++)
    {
        if(a[i]==1)
            su[c]=i,b[i]=c,c++;
        for(int j=1;j<c&&su[j]*i<MAXN;j++) {
            a[su[j] * i] = 0;
            if(i%su[j]==0)break;
        }
    }
}
int p[MAXN];
int pk[130][MAXN];
int main()
{
    prime();
    int cnt=0;
    for(int i=4;i<=MAXN;i++){
        if(a[i]==0)he[++cnt]=i;//合数
    }
    //cout<<he[1]<<" "<<he[2]<<" "<<he[3]<<endl;
    for(int i=1;i<=cnt;i++){
        for(int j=he[i];j<=MAXN;j+=he[i])//合数的倍数,肯定有这个合数作为他的因子
            p[j]++;
    }
    int ma=0;
    for(int i=1;i<=MAXN;i++)
    ma=max(ma,p[i]);
    //cout<<ma<<endl;
    memset(pk,0, sizeof(pk));
    for(int i=1;i<=122;i++)
        for(int j=4;j<=MAXN;j++){
            pk[i][j]=pk[i][j-1];
            if(p[j]==i)pk[i][j]++;//遇到等于i的++
        }
    //cout<<pk[2][8]<<endl;
    int n,m;
    scanf("%d%d",&n,&m);
    while(m--){
        //int ans=0;
        scanf("%d",&k);
        if(k>122)
            printf("0\n");//特判,小于1e5的数的合因子个数不可能超过122
        else
        printf("%d\n",pk[k][n]);
    }
    return 0;
}
/*
 
 */
发布了142 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44091178/article/details/104227696