wayne 发表于 2019-2-13 11:19:43

完美差分集 Perfect Difference Sethttp://mathworld.wolfram.com/PerfectDifferenceSet.html
A set of residues http://mathworld.wolfram.com/images/equations/PerfectDifferenceSet/Inline1.gif (mod http://mathworld.wolfram.com/images/equations/PerfectDifferenceSet/Inline2.gif) such that every nonzero residue can be uniquely expressed in the form http://mathworld.wolfram.com/images/equations/PerfectDifferenceSet/Inline3.gif. Examples include http://mathworld.wolfram.com/images/equations/PerfectDifferenceSet/Inline4.gif (mod 7) and http://mathworld.wolfram.com/images/equations/PerfectDifferenceSet/Inline5.gif (mod 13). A necessary condition for a difference set to exist is that http://mathworld.wolfram.com/images/equations/PerfectDifferenceSet/Inline6.gifbe of the form http://mathworld.wolfram.com/images/equations/PerfectDifferenceSet/Inline7.gif. A sufficient condition is that http://mathworld.wolfram.com/images/equations/PerfectDifferenceSet/Inline8.gif be a prime power. Perfect sets can be used in the construction of perfect rulers.

mathe 发表于 2019-2-13 11:42:29

#include<stdio.h>
#include <string.h>

#ifndef N
#define N5
#endif
#define TS ((N-1)*N+1)
#define WORDC   ((TS+sizeof(int)-1)/sizeof(int))
#define OFFSET(x)((x)/32)
#define INDEX(x)   ((x)&31)
#define ISSET(x)   ((ts&(1<<INDEX(x)))!=0)
#define REVERT(x)(ts^=(1<<INDEX(x)))

int db;
int cc;
int du;
int ts;
int sel;

void set_used(int x)
{
    if(!ISSET(x)){
       REVERT(x); REVERT(TS-x);
    }
}

void set_unused(int x)
{
    if(ISSET(x)){
       REVERT(x); REVERT(TS-x);
    }
}

void init()
{
    db=1; cc=1; du=1;sel=1;
    set_used(1);
}

int left_test(int row, int rc)
{
    int cur_sum=sel;
    int k;
    for(k=rc-1;k>=0;k--){
      cur_sum+=db;
      if(cur_sum<TS&&!ISSET(cur_sum)){
            set_used(cur_sum);
            continue;
      }
      for(;k<rc-1;k++){
            cur_sum-=db;
            set_unused(cur_sum);
      }
      return 0;
    }
    return 1;
}

int right_test(int row, int rc)
{
    int cur_sum=sel;
    int k;
    for(k=0;k<rc;k++){
      cur_sum+=db;
      if(cur_sum<TS&&!ISSET(cur_sum)){
             set_used(cur_sum);
             continue;
      }
      for(;k>0;k--){
            cur_sum-=db;
            set_unused(cur_sum);
      }
      return 0;
    }
    return 1;
}

void reverse(int r, int c)
{
    int i;
    for(i=0;i<c/2;i++){
       int tmp=db;
       db=db;
       db=tmp;
    }
}

int merge_test(int r1, int c1, int r2, int c2, int d1, int d2)
{
    int i,j;
    int tsb;
    if(d1<0)reverse(r1,c1);
    if(d2<0)reverse(r2,c2);
    db=sel;
    memcpy(tsb,ts,sizeof(tsb));
    for(i=0;i<=c2;i++)db=db;
    for(i=0;i<=c1;i++){
       int sum=0;
       for(j=i;j<=c1;j++)sum+=db;
       if(i<c1){
         if(sum>=TS||ISSET(sum)){
                goto restore_state;
         }
         set_used(sum);
       }
       for(;j<c1+c2+1;j++){
         sum+=db;
         if(sum>=TS||ISSET(sum)){
            goto restore_state;
         }
         set_used(sum);
       }
    }
    for(i=r2;i<cc-1;i++){//move other row forward
      for(j=0;;j++){
            db=db;
            if(db==0)break;
      }
    }
    cc--;
    du++;
    return 1;
restore_state:
    db=0;
    if(d1<0)reverse(r1,c1);
    if(d2<0)reverse(r2,c2);
    memcpy(ts,tsb,sizeof(tsb));
    return 0;
}

void merge_revert(int r1, int c1, int r2, int c2, int d1, int d2)
{
    int i,j;
    for(i=cc-1;i>=r2;i--){
      for(j=0;;j++){
            db=db;
            if(db==0)break;
      }
    }
    cc++;du--;
    for(i=0;i<=c1;i++){
       int sum=0;
       for(j=i;j<=c1;j++)sum+=db;
       if(i<c1){
         set_unused(sum);
       }
       for(;j<c1+c2+1;j++){
         sum+=db;
         set_unused(sum);
       }
    }
    db=0;
    for(i=0;i<=c2;i++){
       db=db;
    }
    if(d1<0)reverse(r1,c1);
    if(d2<0)reverse(r2,c2);
}
void left_unset(int row, int rc)
{
    int cur_sum=sel;
    int k;
    for(k=rc-1;k>=0;k--){
      cur_sum+=db;
      set_unused(cur_sum);
    }
}

void right_unset(int row, int rc)
{
    int cur_sum=sel;
    int k;
    for(k=0;k<rc;k++){
      cur_sum+=db;
      set_unused(cur_sum);
    }
}

void go_next_sel()
{
    for(;sel<TS&&ISSET(sel);sel++);
}

int get_row_len(int row)
{
    int j;
    for(j=0;j<N;j++){
       if(db==0)return j;
    }
    return j;
}

void output_result()
{
    int sum=TS;
    int k;
    for(k=0;k<N-1;k++){
       printf("%d ",db);
       sum-=db;
    }
    printf("%d\n",sum);
}

void try_next()
{
    int try_sel;
    int i,j;
    go_next_sel();
    try_sel=sel;
    if(sel==TS){
      output_result();
      return;
    }
    set_used(sel);
    if(du+cc<=N-2){
      //try use sel in new row
      db=sel;db=0;cc++;du++;
      try_next();
      sel = try_sel;//restore
      du--;cc--;
    }
    if(du+cc<=N-1){
      for(i=0;i<cc;i++){//try append after the right of one row
      int j=get_row_len(i);
      if(left_test(i,j)==0)continue;
      db=sel;db=0;
      du++;
      try_next();
      sel=try_sel;du--;db=0;
      left_unset(i,j);
      }
      for(i=0;i<cc;i++){//try insert before first element
      int j=get_row_len(i);
      if(j<=1)continue;
      if(right_test(i,j)==0)continue;
      int k;
      for(k=j;k>=0;k--)db=db;db=sel;
      du++;
      try_next();
      sel=try_sel;du--;
      for(k=0;k<=j;k++)db=db;
      right_unset(i,j);
      }
    }
    for(i=0;i<cc;i++){
      int ri=get_row_len(i);
      for(j=i+1;j<cc;j++){//try connect two rows
            int rj=get_row_len(j);
            if(merge_test(i,ri,j,rj,1,1)){
                try_next();
                sel=try_sel;
                merge_revert(i,ri,j,rj,1,1);
            }
            if(rj>1){
                if(merge_test(i,ri,j,rj,1,-1)){
                  try_next();
                  sel=try_sel;
                  merge_revert(i,ri,j,rj,1,-1);
                }
            }
            if(ri>1){
                if(merge_test(i,ri,j,rj,-1,1)){
                  try_next();
                  sel=try_sel;
                  merge_revert(i,ri,j,rj,-1,1);
                }
            }
            if(ri>1&&rj>1){
                if(merge_test(i,ri,j,rj,-1,-1)){
                  try_next();
                  sel=try_sel;
                  merge_revert(i,ri,j,rj,-1,-1);
                }
            }
      }
    }
    set_unused(sel);
}

int main()
{
    init();
    try_next();
    return 0;
}

mathe 发表于 2019-2-13 15:40:30

N=18
9 26 1 17 2 10 4 7 38 5 8 24 15 42 6 22 3 68
17 14 1 7 3 27 6 12 23 5 19 2 51 9 4 16 34 57
2 8 12 31 3 26 1 6 9 32 18 5 14 21 4 13 11 91
6 1 11 26 35 20 2 8 13 4 15 9 5 31 3 50 16 52
4 34 1 27 3 13 2 6 50 5 9 11 12 10 7 19 41 53
4 12 17 5 23 2 24 15 31 6 3 10 1 7 35 32 36 44
1 14 39 19 2 10 28 8 35 6 3 13 4 7 18 5 32 63
16 5 34 12 1 30 2 8 17 37 7 4 15 3 6 14 36 60
6 4 18 39 1 41 7 17 8 5 14 2 31 3 9 11 15 76
8 7 4 6 23 1 12 9 5 38 16 28 3 32 37 2 18 58
17 32 4 24 5 1 13 25 2 10 8 3 52 26 9 7 15 54
3 8 2 15 16 32 7 29 1 5 14 4 22 12 9 50 27 51
29 25 16 30 1 5 9 8 4 7 32 24 18 2 35 3 10 49
17 28 1 12 36 19 25 7 11 4 5 30 3 21 2 8 6 72
14 1 12 23 3 7 21 16 18 22 2 6 11 32 20 5 4 90
12 4 25 2 5 1 9 13 40 11 3 21 26 19 20 18 34 44
4 5 1 19 3 12 2 16 43 8 13 26 24 7 41 27 11 45
24 1 15 28 6 12 11 3 5 2 20 36 35 13 4 38 9 45
13 27 4 1 15 26 8 30 18 7 3 9 2 22 29 6 17 70
27 4 1 35 15 33 25 39 14 8 16 18 3 7 2 11 6 43
12 2 20 9 16 8 13 17 6 4 1 51 19 7 32 3 15 72
36 10 1 4 16 7 17 25 8 26 3 6 13 39 2 12 18 64
7 6 3 14 8 12 27 19 2 24 18 10 1 4 36 35 32 49
28 7 17 3 18 19 13 1 9 2 4 43 36 5 26 8 22 46
1 22 20 7 9 10 5 29 3 8 17 13 48 4 2 12 21 76
31 27 8 15 3 14 16 12 9 1 19 5 39 36 7 4 2 59
2 4 27 9 5 3 12 1 22 32 19 7 11 28 25 24 10 66
14 20 1 30 37 23 15 10 16 2 4 7 33 9 3 5 19 59
35 22 6 13 21 18 9 11 5 26 23 1 29 3 4 8 2 71
43 1 17 9 31 6 2 12 16 5 47 3 4 15 10 13 11 62
37 3 4 10 1 5 22 24 12 13 8 26 9 30 2 29 19 53
1 4 2 16 12 13 8 24 38 44 15 27 10 9 17 3 11 53
14 34 16 10 15 12 1 4 3 36 23 6 18 22 9 2 19 63
6 13 14 8 9 11 1 3 34 2 45 7 18 5 48 16 10 57
7 10 20 5 13 11 3 1 8 31 44 2 19 26 34 16 6 51
38 14 21 1 3 8 45 9 18 10 6 7 17 2 29 15 5 59
1 3 11 20 7 33 10 9 17 22 6 2 16 5 32 12 13 88
2 17 14 8 1 3 25 7 20 30 46 15 38 10 6 5 13 47
9 20 3 1 6 8 26 11 5 12 31 22 13 36 25 2 19 58
13 8 31 17 1 9 2 3 23 7 43 4 20 16 6 19 34 51
10 17 1 7 15 24 20 9 2 3 38 13 6 26 4 12 21 79
2 3 12 6 7 19 8 14 36 1 9 29 4 20 11 45 16 65
21 35 14 23 10 1 6 36 9 16 13 26 2 3 15 4 8 65
10 27 19 24 12 13 32 8 1 6 11 3 2 28 34 35 4 38
1 37 11 24 26 16 29 23 18 33 6 8 13 4 3 2 10 43
12 6 20 2 1 8 5 19 34 10 7 39 4 21 27 30 15 47
6 8 1 2 27 7 13 5 21 22 19 12 4 24 32 10 23 71
7 8 11 16 13 32 12 5 33 1 2 18 4 6 37 9 14 79
1 2 41 12 5 6 8 7 9 4 29 36 18 22 10 27 25 45
38 25 12 16 4 15 24 2 1 6 49 11 10 8 5 17 14 50
10 9 16 5 1 2 42 13 4 11 23 14 12 20 7 29 18 71

wayne 发表于 2019-2-13 16:21:45

mathe能打破纪录吗,:lol

mathe 发表于 2019-2-13 19:01:57

其实这个代码非常容易并行。给个计算机集群应该很容易冲记录:)

wayne 发表于 2019-2-14 08:43:54

计算机集群就算了。我的意思其实是 能不能仅仅利用PC的多核打破纪录,一般的PC都有4-8核。22#的代码还只是单进程的跑,代码里的数据结构不便于任务分解,感觉代码改动会很大

mathe 发表于 2019-2-14 10:32:49

k=p^n        p        n        q=k^2+k+1        phi(q)/(6n)
3        3        1        13        2
4        2        2        21        1
5        5        1        31        5
7        7        1        57        6
8        2        3        73        4
9        3        2        91        6
11        11        1        133        18
13        13        1        183        20
16        2        4        273        6
17        17        1        307        51
19        19        1        831        42
23        23        1        553        78
25        5        2        651        30
27        3        3        757        42
29        29        1        871        132
31        31        1        993        110
32        2        5        1057        30
https://www.cambridge.org/core/services/aop-cambridge-core/content/view/S2040618500034985
也就是说到现在为止找到的解都是符合文章模式的解

白新岭 发表于 2019-2-14 11:37:39

是不是如果手串上的珠子数减1后不能表示成素数或素数的次幂形式的都无解:例如7-1=6=2*3,是合数,所以无解(这合数不包括单素数次幂的形式);11-1=2*5无解;13-1=2*6无解;以后的15,16,19,21,22,23,25,27,29,31,34,35,36,37,39,......,素数和它的次幂在自然数集的占比是很少的,所以这有解的珠子数也很少。

mathe 发表于 2019-2-14 11:40:27

大概阅读了文章,主要思路如下
如果我们要找K棵珠子的手串,其中$K=p^e+1$,其中$p$是素数,记$r=p^e,q=r^2+r+1$, 我们计算的和将要覆盖1,2,...,q。
我们先选择r阶有限域$F_r$,比如取r=3,那么就是模3运算。另外我们需要选择$F_{r^3}$中一个生成元g
比如说我们选择$g$使得$g^3=g-1$,于是$F_{3r}$中任意一个元素可以写成$a+bg+cg^2$形式,其中a,b,c都是$F_r$中元素(也就是0,1,2)
经计算可以得知这样选择的g的阶是$3^3-1=26$,所以验证了g是生成元,也就是$F_{r^3}$中任意一个非零元还可以写成$g^h$的形式,其中$0<=h<=r^3-2=25$
由于,对于任意h满足$0<=h<=r^3-2$,存在唯一的$a_h,b_h,c_h$使得$g^h=a_h+b_hg+c_hg^2$,我们记$h=H(a_h,b_h,c_h)$或$h=H(a_h+b_hg+c_hg^2)$
现在我们把$F_{r^3}$中任意一个非零元素$a+bg+cg^2$看成$F_r$中射影平面上一个点$(a,b,c)$,那么需要注意如果有两个点u,v使得$H(u)-H(v)$是q的倍数,
那么它们表示的是射影平面上的同一个点,或者说存在$k\in F_r*$使得u的每个分量都是v对应分量的k倍.
于是文章证明对于此射影平面任意直线上的点列$P_0,P_1,...,P_r$(每条直线上正好r+1个点), 那么$H(P_0),H(P_1),...,H(P_r)$两两差关于q的余数各不相同。
比如我们选择直线$z=0$,所以上面的点分别为$(1,0,0), (0,1,0), (1,1,0),(1,2,0)$
对应$F_{r^3}$中的数$1,g,1+g,1+2g$,对应$g^0,g^1,g^9,g^3$,所以我们选中了数$0,1,3,9$,选中的数中必然有两个数相差1,通过平移将它们变为0和1,这里这一步可以省略
所以两两差模$q=13$分别为$1,3,9, 12, 2, 8, 10, 11, 6, 4, 5, 7$互不相同,验证了我们的结论。对应4棵珠子为$1-0=1,3-1=2,9-3=6,13-9=4$
选择不同的直线结果会相同。为了获取不同的结果,我们需要选择不同的生成元g,对应的,相当于找到$H(P_0),H(P_1),...,H(P_r)$,我们将每个$H(.)$在乘上一个和q互素的数字在模q就可以得到在不同坐标系下的$H(.)$
比如,我们可以将$g^0,g^1,g^9,g^3$全部指数乘以2得到$g^0,g^2,g^5,g^6$,然后平移为$g^8, g^10, g^0,g^1$,对应四颗珠子为$1-0=1,8-1=7,10-1=2,13-10=3$
通过这种方法,我们可以在$O(r^6)$的时间内构造出所有的解,但是这种方法不能证明不存在其它解

mathe 发表于 2019-2-14 21:51:28

有限射影平面: https://arxiv.org/ftp/math/papers/0611/0611492.pdf
里面说明了如果$n-=1 (mod 4)$或者$n -=2(mod 4)$而且n包含4k+3形式的素因子的奇数次方,那么不存在长度为n+1的手串
页: 1 2 [3] 4
查看完整版本: 手串上穿有六颗珠子,求各珠子上的数字。