自然数除数的颜色
Colors of natural number divisors
我对一个名叫多雷尔的人有这个学校问题,他的生日收到了一个数字n
。
他想用一种颜色给从1到n的所有自然数着色,这样他自己对一个数的所有除数都与这个数字具有相同的颜色。
该问题要求找出可以使用的最大颜色数。
例如,通过n = 5
,您有:
- 1 红
- 2 绿色
- 3 蓝色
- 4 绿色
- 5 黄色
所以在这个例子中,我们需要 4 种颜色。
练习可以在这里找到,但它是罗马尼亚语。
质数出现问题,所以我在想一种方法来计算从1
到n
有多少个素数,然后将其添加到所需的颜色数量中。
我尝试了复杂的解决方案,如实现米勒-拉宾素数测试和埃拉托色尼,但对于网站上的自动测试,它仍然太慢了。
我是否错过了什么,或者解决这个问题的唯一方法是找到 1 到 n 之间的每个素数?
我按照维基百科的例子实现埃拉托色尼:
/* https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Overview */
void prime(uint n) {
if (n < 1) return;
/* Create a list of consecutive integers from 2 through n: (2, 3, 4, ..., n). */
uint size = n - 1;
uint *list = (uint *)malloc(sizeof(uint) * size);
for (uint i = 0; i < size; i++) {
list[i] = i + 2;
}
/* Initially, let p equal 2, the smallest prime number. */
uint p = 2;
uint c = 1;
while (c < n) {
/*
* Enumerate the multiples of p by counting in increments of p from 2p to n,
* and mark them in the list (these will be 2p, 3p, 4p, ...; the p itself should not be marked).
*/
for (uint i = c; i < size; i++) {
if (list[i] % p == 0) {
list[i] = 0;
}
}
/*
* Find the first number greater than p in the list that is not marked.
* If there was no such number, stop.
* Otherwise, let p now equal this new number (which is the next prime).
*/
while (c < n) {
if (list[c] > p) {
p = list[c++];
break;
}
c++;
}
}
/* the numbers remaining not marked in the list are all the primes below n */
for (uint i = 0; i < size; i++) {
if (list[i] != 0) {
printf("%d ", list[i]);
}
}
printf("nn");
}
问题是你一遍又一遍地对单个数字使用算法。如果你想检查很多数字,很多工作可以重用。
我会做这样的事情:
bool * calculatePrimeArray(int n)
{
bool * ret = malloc(n*sizeof(*ret)+1);
for(int i=0; i<n*sizeof(*ret)+1; i++) ret[i]=true;
ret[0]=ret[1]=false;
int cur = 2;
while(cur < n/2+1) {
if(ret[cur])
for(int i=cur*2; i<n; i+=cur) ret[i] = 0;
cur++;
}
return ret;
}
这将返回一个布尔数组 ret,其中 ret[i] 指示 i 是否是素数。
如果要使其对缓存更友好,可以使用位字段而不是布尔变量。
使用@Bromax答案,我让它工作,它在网站上的所有测试中都得了 100 分:
#include <cstdlib>
#include <iostream>
#include <cmath>
#define PRIME 0
#define NOT_PRIME 1
bool *primes(int n) {
bool *ret = (bool *)calloc(n + 1, sizeof(bool));
ret[0] = ret[1] = NOT_PRIME;
uint cur = 2;
while (cur <= sqrt(n)) {
if (ret[cur] == PRIME) {
for (uint i = cur * cur; i <= n; i += cur) {
ret[i] = NOT_PRIME;
}
}
cur++;
}
return ret;
}
int main() {
FILE *input = NULL;
FILE *output = NULL;
input = fopen("primcolor.in", "r");
uint n;
fscanf(input, "%d", &n);
if (n < 1 || n > 50000000) {
fclose(input);
return 1;
}
output = fopen("primcolor.out", "w");
if (n <= 3) {
fprintf(output, "%dn", n);
fclose(input);
fclose(output);
return 0;
}
uint colors = 2;
bool *a = primes(n);
for (uint i = (n / 2 + 1); i <= n; i++) {
if (a[i] == PRIME) {
colors++;
}
}
fprintf(output, "%dn", colors);
fclose(input);
fclose(output);
return 0;
}
正如建议的那样,最快的方法是创建一个数组,用作从0
到n
的所有数字的缓存
相关文章:
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 如何在内核C++中使用1920x1080x16M图形或类似的16M颜色?(VGA)
- 如何在24位SDL_Surface上设置像素的颜色
- 如何从SDL_Surface获取特定像素的颜色
- 列表视图更改选择颜色
- GtkTreeView 交替行颜色
- dx11 渲染到纹理仅显示透明颜色
- 使用 OpenGL 4.5 更改所选顶点的颜色
- 为什么我的 LEGACY OPENGL 颜色反转了?
- 双击更改 mfc 中列表控件中的行的颜色
- 更改 QT 中按钮的颜色
- 当我使用CHAR_INFO结构时,控制台会无缘无故地改变颜色
- 列表视图项的替代颜色
- GLSL 将 uint 转换为浮点颜色
- std::带有颜色和标题的 clog 包装器无法正确打印整数
- Vec3b:r/g/b 颜色的最大值为 254,而不是 255
- 如何将矢量对象更改为不同的颜色?
- PPM 颜色显示错误
- 如何更改 QGraphicsItem 对象的颜色?
- 自然数除数的颜色