时钟巡回

数学女孩2--费马大定理

第一章 将无限宇宙尽收掌心

 

时钟巡回 之 完全巡回的规律

问题描述:  将圆12 等分, 12个点分别标记为【1...12】。 从12点开始每隔 k 个点连一条线。如果 k == 1, 则第一条连线是(12, 2)。完全巡回的定义是 选定某个K, 重复连线的过程,最终圆上所有点都被连接。

 

进一步的抽象: 另 F(x) =  (x + k) mod 12, k > 0,  初始状态下定义域中仅有一个元素即起点, 每次计算完毕都有 x = F(x); 即定义域中始终只有一个值,若 F(x) 的值域为所有的顶点的标号, 则称为完全巡回。 用代码描述如下:(在最后面)

更进一步的思考:

在连线的时候有顺时针和逆时针的区别, K 取 11 和  1 时,就是逆时针和顺时针将12个点相连。而 11 + 1 ==12。 若 a + b == 12, 则 k 取 a 和 k 取 b 效果是一样的。 (逆时针查 7 个点是5, 顺时针查 5 个点还是 5) 由此可将问题的求解范围缩小一半(只需考虑 k 取【1...6】即可)。  若 K 取 2 3 4 6, F(x) 总是一倍一倍的增上去...

最后我的答案:

对于 K【1...11】;

k =  k<=6 ? k : 12-k;

if( 12 % k || k == 1 )

return true;

return false;

书上的解:

m 是圆上点数

if(gcd (m, k) == 1)

return true;

return false;

//////////////////////////////////////////////////////////////

#include <iostream>
#include <cstring>
using namespace std;
#define MAXN 13


int ans[MAXN], from, to, i, j;    // ans[MAXN] 存放值域
int main(){
    for(i=1; i<=11; ++i){          //由于取余运算中会有 0 的出现, 所以标号化为【0...11】
        from = 11;
        to = 0;
        memset(ans, 0, sizeof(ans));
        
        
        while(to != 11){              // 可以肯定最终一定会回到 最初的起点
               to = (from + i) % 12;
               from = to;
               ans[to] = 1;
        }

         for(j=0; j<=11; ++j)
              if(ans[j] == 0)
                 break;                 
         if(j==12)
            cout << " " << i;   
    }
    return 0;
}

//////////////////////////////////////////////////////////////

 

posted @ 2016-07-02 23:05  _Ade  阅读(380)  评论(0编辑  收藏  举报