#include <stdio.h>
/* нод, взято с википедии */
int gcd(int a, int b)
{
while (b != 0)
{
int r = a % b;
a = b;
b = r;
}
return a;
}
/* что то сделать с i */
void doit(int i)
{
printf("do with %i\n", i);
}
/* включая a и не включая b, то есть [a,b) */
void processrange(int a, int b)
{
int len = b - a;
if (len <= 0) {
return; /* диапазон вырожден*/
}
/* поищем хороший шаг */
/* если такое случиться, что шаг не будет найден, то будет 1 */
int step = 1;
for (int i = 3; i < len/2; i+=2) {
if (gcd(i, len) == 1) {
step = i;
break;
}
}
/* собственно цикл */
int ind = 0;
for (int i = 0; i < len; i++) {
doit(a + ind);
ind = (ind + step) % len;
}
}
int main(void) {
processrange(100,200);
return 0;
}
我草拟了代码,快速测试表明它似乎可以解决您的问题。代码是用c99写的(也就是说,变量的声明不是在块的开头使用),所以在gcc中你需要编译
-std=c99
,studio 2013可能无法编译,而2015很可能会应付。但是重写代码不是问题,因此它甚至可以使用古老的编译器。这里的内存消耗是肯定的
O(1)
,因为内存只分配给各种局部变量,没有数组和隐藏的递归。最难的部分是找到步骤。该算法试图找到最小步长。但理论上存在复杂性
O(n)
。该算法直接搜索第一个长数的奇互质数。可以修改此部分以获得所需的值。如果您查看填充可视化,它将看起来像这样。整个范围将分为 step 和 step-1 元素组,首先填充组中的每个第一个元素,然后每秒填充一次,依此类推。也就是说,顺序不是随机的,而是散开的。如果你想要更多的随机性,那么你应该更深入地研究线性同余法并学习如何为其生成系数。