k合因子数

链接:https://ac.nowcoder.com/acm/contest/3004/H

题目描述
合数是指自然数中除了能被1和本身整除外,还能被其他数(0除外)整除的数。
牛牛最近在研究“k合因子数”,所谓“k合数”是指一个数的所有因子中,是合数的因子共有k个。
例如20的因子有1,2,4,5,10,20,其中4,10,20为合数,它有3个合数因子,就称20是一个 “3合因子数”
牛牛想要知道1~n中给定k的情况下k合因子数的数目。
输入描述:
第一行输入两个数字n,m(1≤n,m≤10^5)
表示范围以及查询“k”的数目
接下来m行,每行一个正整数k(1≤k≤n)
查询k合因子数的数目。
输出描述:
一行一个数字,表示k合因子数的数目
输入
10 5
1
2
3
4
5
输出
4
1
0
0
0
说明
1~10的范围内
1合因子数有:4,6,9,10,共4个
2合因子数有:8,共1一个

像中学学新课一样,学了一个新知识点后忍不住反复用,所以,,,

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <math.h>
#include <map>
#include <queue>
#define mo 1000000007
using namespace std;
typedef long long ll;


int ans[100006], anss[100006];

int fun(int n)
{
    int i, a, ans = 1, pri_fac = 0;
    for(i = 2; i*i <= n; i++)
    {
        if(n%i == 0)
        {
            a = 0;
            while(n%i == 0)
            {
                n /= i;
                a++;
            }
            pri_fac++;   //唯一分解定理,求出 n 的素因子 i 总数
            ans = ans * (a+1);  //  唯一分解定理相关公式应用,求出总因子数
        }
    }
    if(n > 1)
    {
        pri_fac++;
        ans *= 2;
    }
    return ans - pri_fac - 1;  // 合因子数 = 总 - 素 - 1,(1既不是素数也不是合数(*^▽^*))
}


int main()
{
    int n, m, i, k;
    scanf("%d%d", &n, &m);
    for(i = 1; i <= n; i++)
        anss[fun(i)]++;
    while(m--)
    {
        scanf("%d", &k);
        printf("%d\n", anss[k]);
    }
    return 0;
}

虽然比较长,但是很直观很好想,AC之后觉得自己无比机智,直到知道这是埃氏筛,,,另一种做法:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <math.h>
#include <map>
#include <queue>
#define mo 1000000007
using namespace std;
typedef long long ll;
const int Maxn = 100006;

int ans[Maxn], cnt[Maxn];
bool prime[Maxn];

int main()
{
    int n, m, k, i, j;
    scanf("%d%d", &n, &m);
    for(i = 2; i <= n; i++)
        prime[i] = 1;      //假设最初都是素数,用埃氏筛
    for(i = 2; i <= n; i++)
    {
        if(prime[i])
            for(j = i+i; j <= n; j += i)
                prime[j] = 0;    // i 是素数,其倍数 j 都是合数
        else
            for(j = i; j <= n; j += i)
                cnt[j]++;    // i 是合数,其倍数 j 都是是含有合数因子 i 的数,j 的合因子数+1 (更新一遍)
    }
    for(i = 2; i <= n; i++)
        ans[cnt[i]]++;   //cnt[i]是 i 的合因子数,已经更新完毕, ans[cnt[i]] 是合因子数为cnt[i]的数的数目
    while(m--)
    {
        scanf("%d", &k);
        printf("%d\n", ans[k]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值