2020牛客寒假算法基础集训营3——H.牛牛的k合因子数【欧拉筛】

题目传送门


题目描述

合数是指自然数中除了能被1和本身整除外,还能被其他数(0除外)整除的数。
牛牛最近在研究 k “k合因子数” ,所谓 k “k合数” 是指一个数的所有因子中,是合数的因子共有k个。
例如 20 20 的因子有 1 , 2 , 4 , 5 , 10 , 20 1,2,4,5,10,20 ,其中 4 , 10 , 20 4,10,20 为合数,它有 3 3 个合数因子,就称20是一个 3 “3合因子数”
牛牛想要知道 1   n 1~n 中给定 k k 的情况下 k k合因子数 的数目。


输入描述:

第一行输入两个数字 n , m ( 1 n , m 1 0 5 ) n,m(1 \leq n,m \leq 10^5) 表示范围以及查询“k”的数目
接下来m行,每行一个正整数 k ( 1 k n ) k(1 \leq k \leq n) 查询k合因子数的数目。


输出描述:

一行一个数字,表示 k k合因子数 的数目


输入

10 5
1
2
3
4
5


输出

4
1
0
0
0


说明

1   10 1~10的范围内
1 4 , 6 , 9 , 10 4 1合因子数有:4,6,9,10,共4个
2 8 1 2合因子数有:8,共1一个


题解

  • 欧拉筛过一遍,预处理一下可能用到的数
  • 在筛一边合数即可
  • 代码注释的挺详细了,很好懂的

AC-Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int maxn = 1e5;
const int mod = 1e9 + 7;


int ans[maxn + 7];
int vec[maxn + 7][500];    // 记录因子
int p[maxn + 7];    // 模拟vector,保障vec[i]的因子依次存放
int n, m;

int cnt = 0; //记录已知素数数量
vector<int> primes; //存放素数的不定长数组
bool judge[maxn+7]; //筛除标记
void primes_init() {
	cnt = 0;
	memset(judge, true, sizeof(judge));
	judge[0] = judge[1] = true;    // 0和1都不是素数
	for (int i = 2; i <= maxn; i++) {
		if (judge[i]) {
			primes.push_back(i);
			cnt++;
		}
		for (int j = 0; j < cnt && i * primes[j] <= maxn; j++) {
			judge[i * primes[j]] = false; //筛除
			if (i % primes[j] == 0) //关键代码
				break;
		}
	}
}

void init() {
	memset(ans, 0, sizeof ans);
	memset(p, 0, sizeof p);
	for (int i = 1; i <= maxn; ++i) 
		for (int j = i; j <= maxn; j += i) 
			vec[j][p[j]++] = i;
}

int main() {
	ios;
	while (cin >> n >> m) {
		init();
		primes_init();
		for (int i = 1; i <= n; ++i) {
			int ccc = 0;    // 合因子数
			for (int j = 0; j < p[i]; ++j)    // 遍历i的所有因子
				if (!judge[vec[i][j]])    // 如果不是素数,即是合数
					++ccc;
			++ans[ccc];    // 记录答案
		}
		while (m--) {
			int k;  cin >> k;
			cout << ans[k] << endl;
		}
	}
	return 0;
}
发布了162 篇原创文章 · 获赞 99 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Q_1849805767/article/details/104229547