zoukankan      html  css  js  c++  java
  • E

    E - 娜娜梦游仙境系列——莫名其妙的插曲

    Time Limit: 2000/1000MS (Java/Others)    Memory Limit: 128000/64000KB (Java/Others)

    Problem Description

    娜娜因为帮桃花村民们解决了一大难题而受到村民们的尊敬,不过由于娜娜还想继续探索这个神奇的世界,只好恋恋不舍地与村民告别。当娜娜离开村庄的一刻,娜娜失忆了!她不记得桃花村的一切,她不记得之前吃了很多糖果,她不记得她为了过湖而跳了半天,甚至她连自己的名字都不记得了!娜娜盲目地四处溜达,突然迎面走来了一个白马王子,他问:“你是Alice吗?”。娜娜心想:“Alice?好熟的名字啊,难道这就是我的名字吗?",便回答:”是的。请问您是?“白马王子很高兴地说:”我叫Bob,我找你找了一辈子了,没有你,我总是被父王忘记,我们回王宫吧!"于是娜娜就迷迷糊糊地被带到了王宫。

    国王:“你就是Alice?怎么士别三日,你变痴呆了啊,你先和我的儿子Bob先玩一玩游戏,我看看你是不是脑子有问题。”娜娜为了证明自己脑子没问题,只好与Bob玩起了游戏。

    游戏规则很简单,一开始有一个集合,集合里有n个不同的数,然后Alice(娜娜)与Bob轮流进行操作,每人都可以任意选择两个数a,b,不妨设a>b,不过要求a-b不在集合中,把a-b放入集合。如果轮到某人,无法进行任何操作,则该人输掉游戏。作为职业博弈选手,娜娜即使失忆了也能凭着身体的直觉去进行最优操作。那么问,当Alice(娜娜)与Bob都沿着最优策略进行,女士优先(即娜娜先手),最终谁会获胜?

    Input

    多组数据,首先是一个正整数t(t<=20),表示数据的组数

    对于每组数据,首先是一个整数n(1<=n<=1,000),然后是n个整数x[i](0<x[i]<=1,000,000,000),表示集合。保证集合元素不会出现相同。

    Output

    对于每组数据,若Alice(娜娜)最终胜利,输出"Win"

    若Bob最终胜利,输出"Lose"

    若无法分出胜负,输出"Draw",(均不包括双引号,注意大小写,建议复制)

    Sample Input

    2
    5
    1 2 3 4 5
    5
    1 2 3 4 6

    Sample Output

    Lose
    Win

    Hint

    样例1,一开始无论娜娜选择哪两个元素,其差值均包括在集合中,故娜娜无法操作,Bob胜利,输出Lose

    样例2,一开始娜娜只能选择1和6这两个元素,并把6-1=5放入集合中,则集合变为1,2,3,4,5,6 Bob无法操作,Alice(娜娜)胜利,输出Win

    题意:有一个n个元素集合,两个人轮流挑两个数,必须满足两数之差不在集合中,然后把两数之差放入集合中,不能操作者为负

    解法:我们注意到,每次放入集合中的是两数之差,所以集合的最大公约数是保持不变的,也就是说集合中的所有数都可以表示成集合的最大公约数的整数倍,(回忆一下辗转相除法计算最大公约数,不断地作差作差作差,最大公约数依然不变)。不妨设这个最大公约数是d,那么这个游戏是否一定会分出胜负呢?答案是肯定的,因为这个操作不会让集合增加更大的数——一直在添加小的数,终止的条件一定是集合中的所有数正好是{d,2d,3d,......,x[max]},其中x[max]为集合中的最大数。那么最终集合有多少个数?x[max]/d个,一开始有n个即这个游戏会进行x[max]/d-n轮,最后一轮是谁,谁就输。所以只要判断x[max]/d-n的奇偶性即可。

    node:解法讲的差不多了,就是求最大公约数的时候,原本我没判断m==1,就是完全遍历一遍,用了372MS,加了之后就成了0MS了。还有一种方法,循环n遍,初始化公约数为第一个数,然后每次和下一个数求公约数,再把公约数替换掉,也是到1结束判断gcd,这种应该更简单。

     1 #include <stdio.h>
     2 #include <string.h>
     3   
     4 int gcd(int a,int b)
     5 {
     6     if(b!=0) return gcd(b,a%b);
     7     else return a;
     8 }
     9   
    10 int main()
    11 {
    12     int t,n,i,j,x[1003],g,m,ma;
    13     while(scanf("%d",&t)==1)
    14     {
    15         while(t--)
    16         {
    17             scanf("%d",&n);
    18             g=ma=0;
    19             for(i=0;i<n;i++)
    20             {
    21                 scanf("%d",&x[i]);
    22                 if(ma<x[i])
    23                     ma=x[i];
    24             }
    25             for(i=0;i<n;i++)
    26             {
    27                 for(j=i+1;j<n;j++)
    28                 {
    29                     m=gcd(x[i],x[j]);
    30                     if(g==0||g>m)
    31                         g=m;
    32                     if(m==1)break;   //当公约数为1,就不需要继续查找了,已经最小
    33                 }
    34                 if(m==1)break;
    35             }
    36             m=ma/g-n;
    37             if(m%2==0)
    38                 printf("Lose
    ");
    39             else
    40                 printf("Win
    ");
    41         }
    42     }
    43     return 0;
    44 }
  • 相关阅读:
    柔性数组
    2015阿里秋招当中一个算法题(经典)
    LAMP环境搭建
    JS和JQuery中的事件托付 学习笔记
    #17 Letter Combinations of a Phone Number
    码农生涯杂记_5
    【C++ Primer每日刷】之三 标准库 string 类型
    扎根本地连接未来 千米网的电商“红海”生存术
    poj 3356
    经验之谈—OAuth授权流程图
  • 原文地址:https://www.cnblogs.com/weigx/p/4429299.html
Copyright © 2011-2022 走看看