这个程序为《数学之美系列程序》之一。
这个问题是:找出所有n位数中的循环数。
一个n位数中的循环数是指该数乘以1到n之后,每位数字顺序发生移位,可以是移动若干位。
例如:142857是一个6位数的循环数,满足以下条件:
142857*1=142857
142857*2=285714
142857*3=428571
142857*4=571428
142857*5=714285
142857*6=857142
经过试算,这样的数并不好找,1到6位数中只有这一个。
给出的程序是按照自顶向下逐步细化的编程方法编写的顺序程序。对于程序员来说这样的编程训练是必要的,毕竟编写顺序程序是常有的事情。
程序如下:
/* 找出所有n位数中的循环数,该数乘以1到n的数后,每位数字顺序发生移位,可以是移动若干位。 * * 例如:142857是一个6位数的循环数,满足以下条件: * 142857*1=142857 * 142857*2=285714 * 142857*3=428571 * 142857*4=571428 * 142857*5=714285 * 142857*6=857142 * */ #include <stdio.h> // 判定n位数v乘以r是否为循环数,变量gethighdigit用于获取v的最高位 int isCycle(int v, int n, int r, int gethighdigit) { int t, i, highdigit; t = v * r; // 乘积有进位则不是循环数 if(t / gethighdigit / 10 > 0) return 0; // 把最高位循环移位到最低位 for(i=1; i<=n; i++) { // 取出最高位 highdigit = t / gethighdigit; // 计算循环移位结果 t = t % gethighdigit * 10 + highdigit; // 循环移位后,某个数是原数的循环移位结果,则该数乘以r为循环数 if(t == v) return 1; } // 所有的循环移位都不是循环数,则原数不是循环数 return 0; } // 判定n位数v是否为循环数 int isCycleNumber(int v, int n) { int i, gethighdigit=1; // 计算用于取最高位的数 for(i=1; i<n; i++) gethighdigit *= 10; // 乘以2到n的数,有一个不是循环数则该数不是循环数 for(i=2; i<=n; i++) if(!isCycle(v, n, i, gethighdigit)) return 0; // 乘以2到n的数,都是循环数,则该数是循环数 return 1; } int main(void) { int n, start=1, end=9, i, j; // 输入n scanf("%d", &n); // 计算n位数的最小值start和最大值end for(i=1; i<n; i++) { start *= 10; end *= 10; end += 9; } // 对所有的n位数,判定该数是否为循环数,若为循环数则输出 for(i=start; i<=end; i++) if(isCycleNumber(i, n)) { printf("%d ", i); for(j=1; j<=n; j++) printf("%d*%d=%d ", i, j, i*j); } return 0; }
输入6时,程序执行结果如下:
6
142857
142857*1=142857
142857*2=285714
142857*3=428571
142857*4=571428
142857*5=714285
142857*6=857142