HDU1848-Fibonacci again and again
题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=1848
这个题目代码不是很复杂,但那个等价类,(SG函数)没怎么理解,
题目难,不过代码不怎么复杂,在网上找了一些解释,
博弈题,一开始好难理解。还是用到了那个定理
对于nim游戏的某个位置(x1,x2,x3),当且仅当它各部分的nim-sum等于0时(即x1⊕x2⊕x3=0),则当前位于必败点
当时我在网络上找教程,介绍了好多,我也花了很长时间才懂的,待会我会给那个大牛的解题报告的链接,这里我就说说我的理解
这道题用到了上面那个定理,有3堆,每次只能从每堆那里移除斐波那契数的石子。由于每堆有不同的取法,所以把可能出现同种情况的数字归为一类。称为等价类。每一个类又对应一个数叫做等价类数
等价类数的算法(0其实就是必败的点,对于一堆来说)
E[0]=0;
等价类数 E[i] 的算法:
从i个中取走 fib[1],fib[2],...,fib[j]<=i 个后剩下i-fib[1], i-fib[2],..., i-fib[j]个
他们的等价类数中没有出现的最小数就是i的等价类数
例如 i=1,
取走fib[1]=1个 i-fib[1]=0,0的等价类数是0,没有出现的最小数就是1
E[1]=1;
例如 i=2,
取走fib[1]=1个 i-fib[1]=1,取走fib[2]=2个 i-fib[1]=0,
1和0的等价类数是1,0,没有出现的最小数就是2
E[2]=2;
例如 i=3
取走fib[1]=1个 i-fib[1]=2,取走fib[2]=2个 i-fib[1]=1,取走fib[3]=3个 i-fib[1]=0,
2,1和0的等价类数是2,1,0,没有出现的最小数就是3
E[3]=3;
例如 i=4
取走fib[1,2,3]=1,2,3个 剩下3,2,1,没有出现的最小数就是0
E[4]=0; 4是必败点
例如 i=5
取走fib[1,2,3,4]=1,2,3,5个 剩下4,3,2,0,等价类数是 0,3,2,0没有出现的最小数就是1
E[5]=1;
这样就得到了一个等价类数数组。接着就运用那个定理,如果一开始就出现必败点,即(e[n] ^ e[m] ^ e[p]) == 0。那么按照最优走法则必输。其它情况必赢。
详细可看详解。
http://hi.baidu.com/king___haha/blog/item/9addc65ae96948272934f029.html
代码(code)
#include<stdio.h>
#include<string.h>
int main(void)
{
int i,j,k,n,m,p;
int a[1005],b[20],c[16];//才数组为什么只要开到16呢?
b[1]=1; b[2]=2;
for(i=3;i<=16;i++)
b[i]=b[i-1]+b[i-2];
a[0]=0; a[1]=1;
for(i=2;i<=1000;i++)
{
a[i]=i;
memset(c,0,sizeof(c));
for(j=1;b[j]<=i;j++)
{
c[a[i-b[j]]]=1;
}
for(j=0;j<=15;j++)//为什么只要15看可以了呢?
{
if(c[j]==0)
{
a[i]=j;
break;
}
}
}
while(scanf("%d%d%d",&n,&m,&p)==3&&(n+m+p))
{
if(a[n]^a[m]^a[p])
printf("Fibo\n");
else
printf("Nacci\n");
}
return 0;
}
hdu1848 Fibonacci again and again 3堆
解题报告
fib[1..]={1,2,3,5,8,13,21,...};是菲波那契数列,fib[]<=1000
每次只能取 fib[i]个
1. 如果只有1堆m个,m是某个fib[i],m是必胜点,m=1,2,3,5,8,13,21,...是必胜点
易知0,4 是必败点.如果从m个中取走 k个(k=fib[i]) ,m-k是必败点
则 m是必胜点.
6-2=7-3=9-5=4是必败点, 6,7,9 是 必胜点
m=10,m-1=9,m-2=8,m-3=7,m-5=5,m-8=2
从m=10中所有取法后都是必胜点 ==> m=10是必败点
这样当只有1堆时我们可以求所有必败点,用 w[1001]表示,w[i]=0表示i是必败点
w[i]=1表示i是必胜点,
w[0]=0;w[1]=w[2]=w[3]=1;
for(i=4;i<=1000;i++)
{
for(j=1;fib[j]<=i;j++) if(w[i-fib[j]==0){w[i]=1;break;}
//取所有的Fibonacci数都胜,则该点必败
if(fib[j]>i)w[i]=0;
}
只有1堆时所有必败点:
0 4 10 14 20 24 30 36 40 46 50 56 60 66 72 76 82 86 92 96 102 108 112 118 122 128
132 138 150 160 169 176 186 192 196 202 206 212 218 222 228 232 238 242 248 254
260 264 270 274 280 284 290 296 300 306 310 316 322 326 332 338 342 348 352 358
364 368 374 378 384 388 394 400 406 410 416 420 426 430 436 442 446 452 456 462
468 472 478 484 488 494 498 504 510 514 520 524 530 534 540 552 556 562 566 572
576 582 588 592 598 602 608 618 635 644 662 672 688 694 698 704 708 714 723 730
734 740 750 754 766 772 776 782 791 798 808 814 818 824 830 834 840 844 850 854
860 866 872 876 882 886 892 896 902 908 912 918 922 928 934 938 944 950 954 960
964 970 976 980 986 990 996 1000
2. 有2堆m个和 n个
如果 m和 n都是 (1堆的)必败点,则2堆 (m,n) 也是必败点
一般 有 必败+必败=必败, 这里+不是把2队合为1堆
必败+必胜=必胜
必胜+必胜=?不一定
例如 2堆 (4,10) 是必败
(4, 5) 是必胜
易知 ( m,m )必败
定义: 如果 (m,n) 必败,则称 m和n等价
等价是相等的推广:m=n, m和n等价
只有1堆时所有必败点都和0等价,我们说只有1堆时所有必败点是第0类的或他的等价类数是0;
2堆 (1,5) 是必败的,5和1等价,和1等价的m叫做他的等价类数是1
2堆时的情况用 w2[m1][m2] 表示,w2[m1][m2]=0表示 (m1,m2)必败,
w2[m1][m2]=1表示 (m1,m2)必胜
用前面方法可算出等价类数是1的数,例如 1,5,11的等价类数是1
可以进行等价代换例如 3堆 1,5,7 可代换为 1,1,7,是必胜的
3. 结论(不证明了) 如果算出 m,n,p的等价类数是,E[m],E[n],E[p]
令 s=E[m]^E[n]^E[p]
则 s=0 是必败点
等价类数的算法
E[0]=0;
等价类数 E[i] 的算法:从i个中取走 fib[1],fib[2],...,fib[j]<=i 个后剩下
i-fib[1], i-fib[2],..., i-fib[j]个
他们的等价类数中没有出现的最小数就是i的等价类数
例如 i=1,取走fib[1]=1个 i-fib[1]=0,0的等价类数是0,没有出现的最小数就是1
E[1]=1;
例如 i=2,取走fib[1]=1个 i-fib[1]=1,取走fib[2]=2个 i-fib[1]=0,
1和0的等价类数是1,0,没有出现的最小数就是2
E[2]=2;
例如 i=3,取走fib[1]=1个 i-fib[1]=2,取走fib[2]=2个 i-fib[1]=1,取走fib[3]=3个 i-fib[1]=0,
2,1和0的等价类数是2,1,0,没有出现的最小数就是3
E[3]=3;
例如 i=4,取走fib[1,2,3]=1,2,3个 剩下3,2,1,没有出现的最小数就是0
E[4]=0; 4是必败点
例如 i=5,取走fib[1,2,3,4]=1,2,3,5个 剩下4,3,2,0,等价类数是 0,3,2,0没有出现的最小数就是1
E[5]=1;
//计算等价类数
E[0]=0;E[1]=1;
for(i=2;i<=1000;i++)
{ //首先假设 i<=1000时 等价类数<=15
for(j=0;j<=15;j++)h[j]=0;// h[j]==0, j没有出现,h[j]=1,j出现
for(j=1;fib[j]<=i;j++)
{
h[ E[i-fib[j]] ]=1;
}
for(j=0;j<=15;j++)if(h[j]==0){E[i]=j;break;}//h[j]=0,j没有出现
}
因此计算步骤是:
1.计算菲波那契数列fib[i],计算到 fib[i]>1000为止
2.计算等价类数 E[i]
3. 同上面的 3
HDU1848-Fibonacci again and again的更多相关文章
- HDU1848 Fibonacci again and again SG函数
Fibonacci again and again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Jav ...
- hdu-------(1848)Fibonacci again and again(sg函数版的尼姆博弈)
Fibonacci again and again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Jav ...
- HDU1848 Fibonacci again and again(SG 函数)
任何一个大学生对菲波那契数列(Fibonacci numbers)应该都不会陌生,它是这样定义的: F(1)=1; F(2)=2; F(n)=F(n-1)+F(n-2)(n>=3); 所以,1, ...
- hdu1848 Fibonacci again and again [组合游戏]
http://acm.hdu.edu.cn/showproblem.php?pid=1848 Problem Description 任何一个大学生对菲波那契数列(Fibonacci numbers) ...
- hdu1848 Fibonacci again and again(SG游戏功能)
现在的变化是看不清楚SG功能什么寻求方法 临时模板标题是首当 性能mex1它正在寻求g(x) 然后XOR #include<cstdio> #include<iostream> ...
- HDU1848 Fibonacci again and again 博弈 SG函数
题意:三堆石子,每次能拿走斐波那契数个石子,先取完石子胜,问先手胜还是后手胜 石子个数<=1000 多组数据 题目链接:http://acm.hdu.edu.cn/showproblem.ph ...
- 【博弈论】【SG函数】hdu1848 Fibonacci again and again
某个状态的SG函数被定义为 除该状态能一步转移到的状态的SG值以外的最小非负整数. 有如下性质:从SG值为x的状态出发,可以转移到SG值为0,1,...,x-1的状态. 不论SG值增加与否,我们都可以 ...
- $HDU1848\ Fibonacci\ again\ and\ again$ 博弈论
正解:博弈论 解题报告: 传送门! 首先按照套路显然是考虑先预处理出所有数的$SG$函数值然后全局的$SG$就是$SG(n)$^$SG(m)$^$SG(p)$,这儿应该麻油问题$QwQ$? 然后就考虑 ...
- sg函数小结
sg函数小结 sg函数是处理博弈问题的重要工具. 我们知道sg(x)=mex{sg(j)|x能到达状态j} sg(x)=0时代表后手赢,否则先手赢. 对于一个问题,如果某些子问题是相互独立的,我们就可 ...
随机推荐
- 标签(改变样式style)
id可以换为class,class对应的名字可以多个一样 <div class="box">box1</div> <div class="b ...
- Python3基础 当函数中的局部变量与全局变量同名了,各管各的
镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...
- 关于JSON.parse在ie6,ie7下未定义的issue
情况是这样的: 在ie6下出现一个js error,说是JSON.parse为定义,一查,才知道,ie6,ie7不支持JSON. solution:只要在使用JSON之前加载个json2.js就行了. ...
- DataGridView如何实现列标头带数据筛选功能,就象Excel高级筛选功能一样
'近日有本论坛网友问:DataGridView如何实现列标头带数据筛选功能,就象Excel高级筛选功能一样 '今晚正好闲着没事,加之以前也没用到过这个需求,所以就写了个模拟功能,供各位坛友酌情参考. ...
- 时间轴CSS的Demo
一.CSS代码(HTML5支持) /*time-line.css*/ .timeline { position: relative; padding: 20px 0 20px; list-style: ...
- Linux:网络yum源设置
网络yum源,最大的网易(163)算是一个,无论是速度还是软件版本,都非常的不错,将yum源设置为163yum,可以提升软件包安装和更新的速度,同时避免一些常见软件版本无法找到.具体设置方法如下: 1 ...
- 2快速掌握OMD
我们已经知道使用ArcGIS Engine开发,也就意味着我们要和接口打交道,ArcGIS Engine中提供的接口和类加起来估计上万,但是用过ArcGIS Engine的人,知道这个数字不为过.Ar ...
- ural1019 Line Painting
Line Painting Time limit: 2.0 secondMemory limit: 64 MB The segment of numerical axis from 0 to 109 ...
- CSS实现单行、多行文本溢出显示省略号
单行显示省略号 overflow: hidden; text-overflow:ellipsis; white-space: nowrap;多行显示省略号 display: -webkit-box; ...
- bzoj1061 志愿者招募
bzoj1061 志愿者招募 Description 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难 题:为即将启动的奥运新项目招募一批短期志愿者.经 ...