1527】【POJ
阿新 • • 發佈:2018-12-12
題幹:
有兩堆石子,數量任意,可以不同。遊戲開始由兩個人輪流取石子。遊戲規定,每次有兩種不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在兩堆中同時取走相同數量的石子。最後把石子全部取完者為勝者。現在給出初始的兩堆石子的數目,如果輪到你先取,假設雙方都採取最好的策略,問最後你是勝者還是敗者。
Input
輸入包含若干行,表示若干種石子的初始情況,其中每一行包含兩個非負整數a和b,表示兩堆石子的數目,a和b都不大於1,000,000,000。
Output
輸出對應也有若干行,每行包含一個數字1或0,如果最後你是勝者,則為1,反之,則為0。
Sample Input
2 1 8 4 4 7
Sample Output
0 1 0
解題報告:
威佐夫博弈。注意向下取整。二分尋找k。找到後再判斷是否還會有比k大的數也滿足向下取整以後是a。(反正這個for迴圈也不會執行很多次,於是乎果斷暴力了一下)(因為我才可能會有多個k滿足這個要求,畢竟qq的值是1.618左右,,也不算很大)然後看看可不可以找到b滿足即可。
主要就是用到了威佐夫博弈的公式。
AC程式碼:
#include<bits/stdc++.h> #define ll long long using namespace std; int a,b; double qq; bool ok(int mid) { if(floor(mid*qq) >= a) return 1; return 0; } int main() { qq = (1+sqrt(5))/2; int l,r,mid; while(~scanf("%d%d",&a,&b)) { int flag = 0; if(a > b) swap(a,b); l=1,r=b; mid = (l+r) /2; while(l<r) { mid = (l+r)/2; if(ok(mid)) r=mid; else l=mid+1; } int tmp = floor(l*qq); if(tmp == a) { for(int i = l; i<=l+100; i++) { if(floor(i*qq) > a) break; if(b==a+i) flag=1; } } if(flag) puts("0"); else puts("1"); } return 0 ; } //ak =[k(1+√5)/2],bk= ak + k (k=0,1,2,...n 方括號表示取整函式)
AC程式碼2:(直接用庫函式去xjbg)(題解)
/* 任給一個局勢(a,b),怎樣判斷它是不是奇異局勢呢?我們有如下公式: ak =[k(1+√5)/2],bk= ak + k (k=0,1,2,…,n 方括號表示取整函式) 奇妙的是其中出現了黃金分割數(1+√5)/2 = 1。618…,因此,由ak,bk組成的矩形近 似為黃金矩形,由於2/(1+√5)=(√5-1)/2,可以先求出j=[a(√5-1)/2],若a=[ j(1+√5)/2],那麼a = aj,bj = aj + j,若不等於,那麼a = aj+1,bj+1 = aj+1 + j + 1,若都不是,那麼就不是奇異局勢。然後再按照上述法則進行,一定會遇到奇異 局勢。 */ #include<stdio.h> #include<math.h> #include<algorithm> using namespace std; int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { if(n>m)swap(n,m); // printf("n=%d,m=%d\n",n,m); int k=(int)(n*(sqrt(5)-1)/2.0); if((int)(k*(sqrt(5)+1)/2.0)==n&&m==n+k) printf("0\n");//奇異局勢 else if((int)((k+1)*((sqrt(5)+1)/2.0))==n&&m==n+k+1) printf("0\n");//奇異局勢 else printf("1\n");//非奇異局勢 } return 0; }
AC程式碼3:(同上)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
int n,m,k,t;
while(scanf("%d%d",&n,&m )==2)
{
if(n<m)//交換n,m的值。使n>m ;
{
n^=m;
m^=n;
n^=m;
}
k=n-m;
t=k*(1+sqrt( 5 ))/2;
if(t==m)
printf("0\n");
else
printf("1\n");
}
return 0;
}