- 注册时间
- 2009-5-22
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 38554
- 在线时间
- 小时
|
楼主 |
发表于 2018-5-11 15:59:54
|
显示全部楼层
Number of cells that the first player can capture in the 1-dimensional cell capturing game with n cells
1, 2, 3, 2, 3, 4, 5, 5, 5, 5, 7, 7, 7, 7, 8, 9, 10, 9, 10, 11, 11, 12, 12, 12
以上是$a(1)$到$a(24)$的数据。
$a(25)$算了好几个小时了,还没出结果。
#####
$a(25)$用了$8$个小时终于算完了,结果是$13$。
我的程序对$a(26)$无能为力了(估计需要计算$10$天)。
#####
我改进了程序:
- #include<cstdio>
- #include<cstring>
- const int m=64;
- char a[m],n;
- char f(char b,char w)
- {
- char s[m],i,c=0,d=0,e=1,g;
- memcpy(s,a,n);
- if(b>1)c=n;
- for(i=0;i<n;i++)
- if(!a[i])
- {
- e=0;
- a[i]=b;
- if(i)a[i-1]=b;
- if(i<n-1)a[i+1]=b;
- g=f(b^3,c);
- memcpy(a,s,n);
- if(b>1)
- {
- if(g<c)c=g;
- if(c<=w)return c;
- }
- else
- {
- if(g>c)c=g;
- if(c>=w)return c;
- }
- }
- else
- if(a[i]<2)d++;
- if(e)return d;
- return c;
- }
- int main()
- {
- for(n=0;n<m;n++)
- printf("%d: %d\n",n,f(1,n));
- return 0;
- }
复制代码
上述C++代码仅运行$1$小时就计算到了$a(32)$,但是继续运行$3$天也只是多算了$5$项,计算到了$a(37)$而已。
该程序的输出结果如下:
- 0: 0
- 1: 1
- 2: 2
- 3: 3
- 4: 2
- 5: 3
- 6: 4
- 7: 5
- 8: 5
- 9: 5
- 10: 5
- 11: 7
- 12: 7
- 13: 7
- 14: 7
- 15: 8
- 16: 9
- 17: 10
- 18: 9
- 19: 10
- 20: 11
- 21: 11
- 22: 12
- 23: 12
- 24: 12
- 25: 13
- 26: 14
- 27: 14
- 28: 15
- 29: 15
- 30: 16
- 31: 16
- 32: 17
- 33: 17
- 34: 18
- 35: 18
- 36: 19
- 37: 19
复制代码
从$a(0)$开始,该数列更新如下:
Number of cells that the first player can capture in the 1-dimensional cell capturing game with n cells
0, 1, 2, 3, 2, 3, 4, 5, 5, 5, 5, 7, 7, 7, 7, 8, 9, 10, 9, 10, 11, 11, 12, 12, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19
继续改进程序:
- #include<map>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const int m=96;
- char a[m],n,c;
- map<pair<unsigned __int64,unsigned __int64>,char>r;
- char f(char b)
- {
- unsigned char p[12]={0,0,0,0,0,0,0,0,0,0,0,0},i,j,ps=0,ts=0,h=0;
- unsigned int t[2]={0,0},s2=0,s3=0,s4=0;
- for(i=0;i<n;i++)
- if(!a[i])
- {
- for(j=i+1;j<n&&!a[j];j++);
- if(j>=n&&!i)s2=3,t[0]=n;
- else
- if(j-i<3)
- if(j-i<2&&(j>=n||!i))s2++;
- else
- if(j-i>1&&j<n&&i&&a[i-1]^a[j])s4++;
- else
- {
- if(j-i>1&&b==a[j]&&j<n&&i)h++;
- s3++;
- }
- else
- if(j>=n||!i)t[ts++]=j-i<<1|a[i?i-1:j]==b;
- else p[ps++]=(j-i)*3+(a[i-1]==b)+(a[j]==b);
- i=j;
- }
- else h+=a[i]==b&&(!i||a[i-1])&&(i>n-2||a[i+1]);
- sort(p,p+ps),sort(t,t+ts);
- pair<unsigned __int64,unsigned __int64>o;
- for(o.first=s2<<30|s3<<23|s4<<16|t[0]<<8|t[1],i=0;i<4;i++)o.first=o.first<<8|p[i];
- for(o.second=0;i<12;i++)o.second=o.second<<8|p[i];
- if(r.find(o)!=r.end())return b<2?h+r[o]:n-h-r[o];
- char s[m],c=0,g;
- memcpy(s,a,n);
- if(b>1)c=n;
- for(i=0;i<n;i++)
- if(!a[i])
- {
- a[i]=b;
- if(i)a[i-1]=b;
- if(i<n-1)a[i+1]=b;
- g=f(b^3);
- memcpy(a,s,n);
- if((b>1)^(g>c))c=g;
- }
- r[o]=b<2?c-h:n-h-c;
- return c;
- }
- int main()
- {
- for(r[make_pair(0,0)]=n=0;n<m;n++)
- c=f(1),printf(c^n/2+1?"%d: %d\n":"",n,f(1));
- return 0;
- }
复制代码
该程序记录每种碎片组合的结果,以后遇到相同的碎片组合就直接查询之前记录下来的结果,不再重复计算。
于是效率大增,不到$2$小时就计算到了$a(55)=28$,可惜在计算$a(56)$时内存超出了$2GB$,异常退出了。
由于大部分的项都满足$a(i)=\lfloor i/2\rfloor+1$,该程序只输出$a(i)\ne\lfloor i/2\rfloor+1$的特殊项,结果如下:
- 0: 0
- 3: 3
- 4: 2
- 7: 5
- 10: 5
- 11: 7
- 14: 7
- 17: 10
- 18: 9
- 24: 12
复制代码
#####
继续改进程序,在内存即将超出时不再存储新的碎片组合的结果,
而是利用已有碎片组合的结果重复计算新的碎片组合的结果,
运行$3$天计算到了$a(67)=34$,依然没有出现新的特殊项。 |
|