日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU2176 【 Nim博弈】 SG函数求解

發布時間:2024/10/6 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU2176 【 Nim博弈】 SG函数求解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

取(m堆)石子游戲

m堆石子,兩人輪流取.只能在1堆中取.取完者勝.先取者負輸出No.先取者勝輸出Yes,然后輸出怎樣取子.例如5堆 5,7,8,9,10先取者勝,先取者第1次取時可以從有8個的那一堆取走7個剩下1個,也可以從有9個的中那一堆取走9個剩下0個,也可以從有10個的中那一堆取走7個剩下3個.

Input

輸入有多組.每組第1行是m,m<=200000. 后面m個非零正整數.m=0退出.?

Output

先取者負輸出No.先取者勝輸出Yes,然后輸出先取者第1次取子的所有方法.如果從有a個石子的堆中取若干個后剩下b個后會勝就輸出a b.參看Sample Output.?

Sample Input

2 45 45 3 3 6 9 5 5 7 8 9 10 0

Sample Output

No Yes 9 5 Yes 8 1 9 0 10 3

Nim游戲:

有N堆石子,每堆石子的個數是有限的,合法的操作是:選擇一堆石子,拿走若干顆,不能不拿;最后拿走最后一顆石子者勝。

結論:

必敗狀態:a1^a2^......^an=0(奇異局勢)

必勝狀態:a1^a2^.......^an=k (其中k不為零)

遇到奇異局勢的選手必敗

證明:

N=1時,先手第一次可以全部取完,先手必勝;

1.對于某個局面(a1,a2,...,an),若a1^a2^...^an!=0,一定存在某個合法的移動,將ai改變成ai'后滿足a1^a2^...^ai'^...^an=0。

不妨設a1^a2^...^an=k,則一定存在某個ai,它的二進制表示在k的最高位上是1(否則k的最高位那個1是怎么得到的)。

這時ai^k<ai一定成立。則我們可以將ai改變成ai'=ai^k,此時?a1^a2^...^ai'^...^an=a1^a2^...^an^k=0。

2.對于某個局面(a1,a2,...,an),若a1^a2^a3...^an=0,先手遇到奇異局勢,先手必敗;

一定不存在某個合法的移動,將ai改變成ai'后,足?a1^a2^...^ai'^...^an=0。

因為異或運算滿足消去率,由a1^a2^...^an=a1^a2^...^ai'^...^an可以得到ai=ai'。所以將ai改變成ai'不是一個合法的移動

答案:

  • 如果a1^a2^a3^......^an=0,先手遇到奇異局勢,先手必敗;
  • 如果a1^a2^a3^......^an=k,先手必勝,先手選擇一堆石子,取temp個之后,出現奇異局勢,后手必敗

假設從第 i 堆石子中取走(ai^k)個石子,(a1^a2^a3^...ai^....^an)^k=k^k=0,剩余石子必然是奇異局勢,后手必敗;

  • 若(ai^k) < ai,即從第i堆中取走的石子個數小于等于總個數,那么就可以從這一堆石子中取
  • 若(ai^k) >?ai,即從第i堆中取走的石子個數大于總個數,那么就不可以從這一堆石子中取
  • 在這道題中如果當前是必勝的話,那么就要下一個移動的人必敗,所以就要改變一個ai變成ai'使得原本的a1^...ai^...^an!=0變成a1^...ai'...^an=0,可以利用ai^k<ai' 判斷

    import java.util.*; import java.math.*;public class Main{static int MAXN=(int)(2e5+10);static int[] a=new int[MAXN];//存儲每堆石子的個數static int n;public static void main(String[] args) {Scanner cin=new Scanner(System.in);while(cin.hasNext()) {n=cin.nextInt();if(n==0) break;int ret=0;for(int i=1;i<=n;i++) {a[i]=cin.nextInt();ret^=a[i];//根據Nim游戲的策略,對每堆石子進行異或運算} if(ret==0) {//先手遇到奇異局勢,必敗System.out.println("No");continue;}System.out.println("Yes");//先手取一次之后,讓后手面對奇異局勢for(int i=1;i<=n;i++) {int temp=a[i]^ret;if(temp<=a[i]) System.out.println(a[i]+" "+temp);}}cin.close();} }

    取硬幣游戲?

    時間限制:?1 Sec??內存限制:?128 MB

    題目描述

    現在有n堆硬幣,第i堆硬幣有xi個硬幣。yoyo和灰灰輪流進行操作,每次操作只能選擇一堆硬幣,然后從這一堆硬幣中取任意多個硬幣(1~x,x為該堆最大數量),但不能不取。輪到的人如果沒有硬幣可取,則輸。yoyo先手,誰能獲勝?

    輸入

    首行輸入t,代表t組樣例

    每組樣例第一行輸入n,代表n堆硬幣。n<=1000;

    接下來n個數字(a1,a2,a3......an)代表每堆硬幣的硬幣數。an<=1000;

    輸出

    輸出誰贏。yoyo必勝輸出yoyo,否則輸出zhazhahui

    樣例輸入

    2 3 2 3 4 4 2 3 4 5

    樣例輸出

    yoyo zhazhahui

    分析:

    對于一堆硬幣,假設有x個,則這堆硬幣取一次后,剩余的個數可能是mex={0,1,2.....x-2,x-1},

    SG表示最小的不屬于mex集合的最小非負整數,即SG(x)=x;

    所以ans=x1^x2^x3.......xn;若ans=0,說明先手必敗,否則先手必勝

    #include<bits/stdc++.h> using namespace std;int main() {ios::sync_with_stdio(false);int n,t;cin>>t;while(t--){cin>>n;int x,ans=0;for(int i=0;i<n;i++){cin>>x;ans^=x;}if(ans==0)printf("zhazhahui\n");elseprintf("yoyo\n");}return 0;}

    ?

    總結

    以上是生活随笔為你收集整理的HDU2176 【 Nim博弈】 SG函数求解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。