先上一串数吧,,
(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。
大家发现规律啦吗?
没发现也不要紧,我来给大家说一下其中的奥妙吧,哈哈哈。
咱们先不说(0,0),从第二个开始说,她是以1开始的,而2比1多1,第三个是从3开始的,接着5比3多2,第4个事从4开始的,7比4多3...每一个数对的两个数之间都是从1开始相差2,3,4...再观察每个数对的第一个数,他们都是前面的那些数对中没有出现过的数的最小自然数,因此,稍稍观察一下规律就显而易见啦嘛,程序员最基本的素质就是善于分析数据,找到普遍规律。什么?(0,0)还没说,呵呵,表急。
下面我们先上一个小情景,放松一下吧
有两堆若干个物品,两个人轮流从某一堆或同时从两堆中取相同多的物品,规定每次至少取一个,多者不限,最后取光者得胜(设A,B依次操作,A先进行)。
上概念:
局势:用(ak,bk)(ak ≤ bk ,k=0,1,2,...,n)表示两堆物品的数量并称其为局势。
奇异局势:如果甲面对(0,0),那么甲已经输了,这种局势我们称为奇异局势。
看吧,(0,0)出来啦,,
所以上面的那些数对都叫做奇异局势。
而
a0=b0=0,ak是未在前面出现过的最小自然数,而 bk= ak + k。
ak = 差值 * 1.618
而1.618 = (sqrt(5)+ 1) / 2 。
0.618是黄金分割率。而威佐夫博弈正好是1.618。
奇妙吧!
HDU1527 http://acm.hdu.edu.cn/showproblem.php?pid=1527
这个是最基础的入门题啦,就是套用模板就行拉,没有任何技术含量
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<algorithm> 5 #include<math.h> 6 using namespace std; 7 int main(){ 8 int a,b; 9 while(~scanf("%d%d",&a,&b)){ 10 double k=(sqrt(5.0)+1.0)/2.0; 11 if(a>b){ 12 int t; 13 t=a; 14 a=b; 15 b=t; 16 } 17 int t=b-a; 18 if(a==(int)(k*t)) 19 cout<<"0"<<endl; 20 else cout<<"1"<<endl; 21 } 22 }
对于中间如果a>b,可以直接用c=max(a,b),d=min(a,b),k=c-d;t=(sqrt(5)+1)/2;
之后可以有两种方法d=(int)(k*t)或者c=(int)(k*t*t)
再来一个,,,,
HDU2177 http://acm.hdu.edu.cn/showproblem.php?pid=2177
判断是谁赢和前面的一样,就是多加啦一步怎么取,我个人认为有三种方法,第一种就是从两堆里各拿出想同数量的石子第二种就是从多的一堆里拿出石子,第三种就是从少的一堆拿出石子,而HDU用前面两种就能过。。
代码如下:
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<algorithm> 5 #include<math.h> 6 using namespace std; 7 int main() 8 { 9 int a,b;double k=(sqrt(5)+1)/2.0; 10 while(~scanf("%d%d",&a,&b)&&(a+b)){ 11 12 if(a>b){ 13 int t; 14 t=a; 15 a=b; 16 b=t; 17 } 18 int t=b-a; 19 if(a==(int)(t*k)) 20 {cout<<"0"<<endl;continue;} 21 else {cout<<"1"<<endl; 22 for(int i=1;i<=a;i++){ 23 int m=b-i; 24 int n=a-i; 25 if(n==(int)(t*k)) 26 cout<<n<<" "<<m<<endl; 27 28 } 29 for(int i=b-1;i>=0;i--){ 30 int m=i; 31 int n=a; 32 if(m<n){ 33 int t=m; 34 m=n;n=t; 35 } 36 int s=m-n; 37 if(n==(int)(k*s)) 38 cout<<n<<" "<<m<<endl; 39 } 40 for(int i=a-1;i>=0;i--){ 41 int m=i; 42 int n=b; 43 int s=n-m; 44 if(m==(int)(k*s)) 45 cout<<m<<" "<<n<<endl; 46 } 47 } 48 } 49 }
注释掉的部分就是第三种啦。。
去掉第三种交上去就对啦!!!
去掉第三种交上去就对啦!!!
去掉第三种交上去就对啦!!!
重要的事说三遍。。。