NYOJ 23 取石子(一)
有一堆石子共有n個,A和B輪流取,A先,每次最少取1個,最多取m個,先取完者勝,A,B足夠聰明,問誰先勝?
比較簡單的巴什博弈,若n%(m+1)!=0,A勝,否則B勝。
NYOJ 833 取石子(七)
n個石子擺成一圈,A和B輪流取,每次可以從中取一個或相鄰兩個,先取完者勝,A先取,問誰勝?
若n==1||n==2 則A勝,否則B勝。
NYOJ 161 取石子(四)
兩堆石子分別n,m(n>=m)個,A和B輪流取,有兩種取法,一是在任意的一堆中取走任意多的石子,最少爲一;二是在兩堆中同時取走相同數量的石子。A先取,先取完者勝,問A是否勝?(勝輸出1,負爲0)
著名的威佐夫博奕,
結論:若(n-m)*(sqrt(5.0)+1.0)/2.0!=m ,則A勝,否則負。
#include<iostream>
#include<math.h>
using namespace std;
int main()
{
int a,b;
while(cin>>a>>b)
{
if(a>b)
{
a^=b;
b^=a;
a^=b;
}
double n=((sqrt(5.0)+1)/2.0);
if((a==(int)((b-a)*n)))
cout<<0<<endl;
else
cout<<1<<endl;
}
return 0;
}
NYOJ 837 Wyothoff Game
題意同上取石子(四),不過現在要求前n(n<=10W)個必敗態,比如A面對(0,0)必敗,面對(1,2)(3,5)(4,7)也必敗,現在給一個n,求前n個必敗態。
由上面取石子(四)的題解鏈接可知其第n項爲(n*(sqrt(5.0)+1.0)/2,n*(sqrt(5.0)+1.0)/2+n),由此打一個10W的表即可。
#include<iostream>
#include<math.h>
using namespace std;
int main()
{
int a[100003];
int i,j;
a[0]=0;
double n=(sqrt(5.0)+1)/2;
for(i=1;i<100001;i++)
{
a[i]=(int)(i*n);
}
while(cin>>j)
{
for(i=0;i<=j;i++)
{
printf("(%d,%d)",a[i],a[i]+i);
}
printf("\n");
}
return 0;
}
NYOJ 585 取石子(六)
有n堆石子,每堆石子都有任意個,A和B輪流從取任意堆裏取一定的石子,每次只能從一堆裏至少取一個,A先取,先取完者勝,問誰勝?
此題爲尼姆博弈,
結論:將n個數異或一遍,若不爲0,則A勝,否則B勝。
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
int a[1000];
int n,m,i,j=0;
cin>>n;
while(n--)
{
int sum=0;
scanf("%d",&m);
for(i=0;i<m;i++)
scanf("%d",&a[i]);
for(i=0;i<m;i++)
{
if(a[i]>1)
sum++;j^=a[i];
}
if((j==0&&sum==0)||(j!=0&&sum>0))
cout<<"Yougth"<<endl;
else
cout<<"Hrdv"<<endl;
j=0;
}
return 0;
}
NYOJ888取石子(九)
題意同取石子(六),不過先取完者敗,問誰勝?
尼姆博弈的變形,統計一下所有數一下大於一的個數,並將所有數字異或一遍,若大於一的個數爲0&&異或之後爲0||大於一的個數大於0&&異或之後不爲零,則A(Yougth)勝,否則B(Hrdv)勝,
代碼:
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
int a[1000];
int n,m,i,j=0;
cin>>n;
while(n--)
{
int sum=0;
scanf("%d",&m);
for(i=0;i<m;i++)
scanf("%d",&a[i]);
for(i=0;i<m;i++)
{
if(a[i]>1)
sum++;j^=a[i];
}
if((j==0&&sum==0)||(j!=0&&sum>0))
cout<<"Yougth"<<endl;
else
cout<<"Hrdv"<<endl;
j=0;
}
return 0;
}
NYOJ135取石子(二)
題意同上上取石子(六),不過限定了每堆石子最多可以取的石子數(最少爲一),問A是勝還是敗?(第一行是一個整數T表示測試數據的組數(T<100)每組測試數據的第一行是一個整數N(1<N<100),表示共有N堆石子,隨後的N行每行表示一堆石子,這N行中每行有兩個數整數m,n表示該堆石子共有m個石子,該堆石子每次最多取n(0<=m,n<=2^31))
#include<iostream>
using namespace std;
int main()
{
int n,m,i,j;
int a[100][2];
scanf("%d",&n);
while(n--)
{
int tem=0,d=0;
scanf("%d",&m);
for(i=0;i<m;i++)
{
scanf("%d %d",&a[i][0],&a[i][1]);
}
for(i=0;i<m;i++)
{
d=a[i][0]%(a[i][1]+1);
tem^=d;
}
if(tem==0)
printf("Lose\n");
else
printf("Win\n");
}
return 0;
}
NYOJ358取石子(五)
有一堆石子,A和B輪流從中取一定的石子,但規定:第一次不能取完,至少一個;從第二次開始,每個人取的石子數至少爲1,至多爲對手剛取的石子數的兩倍。A先取,問A是否會勝?斐波那契博弈
結論:若其對應的石子數目剛好是斐波那契數,則A必敗,否則A必勝。
代碼:
這個代碼nyoj過不了,思想沒錯,但我沒找出來是哪錯了。
#include<stdio.h>
unsigned long long a[120];
int main()
{
unsigned long long n;
int i;
a[0]=0;
a[1]=1;
for(i=2;i<120;i++)
a[i]=a[i-1]+a[i-2];
while(~scanf("%llu",&n))
{
int f=0;
for(i=1;i<120;i++)
if(a[i]==n)
{
f=1;
break;
}
if(f)
printf("No\n");
else
printf("Yes\n");
}
return 0;
}