回 帖 发 新 帖 刷新版面

主题:第40次编程比赛第2题题目

取石子游戏的变种:有两堆石子,两个人轮流对这些石子进行操作。在每一次操作中,操作者需要拿走其中一堆石子,并且把另一堆石子分成两堆(可以不相等)留给对方操作。游戏如此进行下去,石子数会越来越少,最后必将出现这样一种情况:某人拿走一堆石子后发现另一堆里只剩1个石子不能再分了。游戏规定此时该操作者取胜。
  这个游戏是不公平的。对于任意一种初始状态,总有一方有必胜策略。所谓有必胜策略是指,无论对方如何操作,自己总有办法取胜。现在给出两堆石子的数量,要求计算先操作的人是否存在必胜策略。

函数原型 bool Stone(char* a,char* b);
a,b是两堆数字的数目,用字符串保存。字符串长度不大于30,并且没有非法字符,没有前导0。
返回值:如果先操作的人存在必胜策略,返回true,否则返回false

内存限制:256M 
时间限制:10S

样例:
a="1"    b="1"    true
a="100"  b="1"    true
a="2"    b="1"    true
a="2"    b="3"    false
a="5"    b="2"    true

提示:不要想太复杂了。

回复列表 (共17个回复)

11 楼

#include<iostream>
#include<math.h>
using namespace std;
 long long pow(int a)
 {   
      long long b(1);
      while(a--)
        b*=10;
        return b;
}

bool Stone(char* a,char* b)
{
   int la=strlen(a);
   int lb=strlen(b);
   long long aa(0),bb(0);
   for(int i=0;i<la;i++)
     aa+=(long long)(a[i]-'0')*pow(la-i-1);
   for(int i=0;i<lb;i++)
    bb+=(long long)(b[i]-'0')*pow(lb-i-1); 
   bool flag_a(false),flag_b(false);
    int remainder_a=aa%5, remainder_b=bb%5;
    if(remainder_a==2||remainder_a==3)
           flag_a=true;
    if(remainder_b==2||remainder_b==3)
           flag_b=true;
   if(flag_a&&flag_b)
      return false;
   else
      return true;

     

12 楼

函数实现如下,没有测试程序

#include <iostream>
#include <stdlib.h>

using namespace std;

bool Stone(char* a,char* b){
     long n1=atol(a),n2=atol(b);
     for(int i=1,j=1;;){
             if((i<=n1&&j>=n1)||(i<=n2&&j>=n2))return 1;
             else if(i>n1&&i>n2)return 0;
             else{
                  i=i*4;
                  j=(j+1)*4;
                  }
                  }
                  }
             
             

13 楼


int str2int(char *str)
{
    int r=0;
    while (*str!=0)
    {
        r=r*10 + (*str -'0');
        str++;
    }
    return r;
}

bool judge(int a,int b)
{
    int b1,b2;
    if ( a==1)
        return true;
    
    if (a==2 || a==3)
    {
        if (b==2 || b==3)
            return false;
        b1=2;        //拆分b为b1,b2
        b2=b-b1;
        while (b1<=b2)
        {
            if (!judge(b1,b2)) //对方失败
                return true;
            b1++;        b2--;
        }
        return false;
    }
    else
    {
        int i;
        for (i=0;i<2;i++)
        {
            b1=2;        //拆分b为b1,b2
            if (i==0)    b2=b-b1;
            else        b2=a-b1;

            while (b1<=b2)
            {
                if (!judge(b1,b2)) //对方失败
                    return true;
                b1++;        b2--;
            }
        }
        return false;
    }
}

bool Stone(char* a,char* b)
{
    int n1,n2;
    n1=str2int(a);
    n2=str2int(b);
    if (n1<=n2)
        return judge(n1,n2);
    else
        return judge(n2,n1);
}

14 楼

题目最好是自己出,不要去COPY以前的题目,网上都要现成的REPORT,而且我认为搞ACM的来这好象不是很合适,

15 楼

bool Stone(char* a,char* b)
{
    char *p=a,*q=b;
    for(;*p!=0;p++);
    for(;*q!=0;q++);
    p--;
    q--;
    return !(*p=='2' || *p=='3' || *p=='7' || *p=='8') || !(*q=='2' || *q=='3' || *q=='7' || *q=='8');
}

16 楼


[em9]简单!!

    
      a="1"   b="2"    true
      a="2"   b="1"    false

17 楼

观察以下数字序列,(分为两行),若开始时两堆石子的数目为第一行的任意两个数字时,则先操作的人必输;若包含一个或一个以上的第二行的数字时,则一定能赢。
--------------------------------------------------------------
第一行: 2 3     7 8      12 13       17 18       22 23  
第二行:1   4 5 6   9 10 11   14 15 16     19 20 21   24 25 26
--------------------------------------------------------------
第一行:27 28      32 33      37 38      42 43
第二行:    29 30 31   34 35 36   39 40 41   44 45 46
--------------------------------------------------------------
    再仔细观察第一行数字的特征,发现该行的数字的末尾数字为'2','3','7','8',所以只要检查字符串a,b的末尾数字就行了。

//判断数字是否为2,3,7,8
int Judge(char *a)
{
    switch(*a)
    {
        case '2':
        case '3':
        case '7':
        case '8':return 1;
        default: return 0;
    }
}
bool Stone(char* a,char* b)
{
    int tag=0;
    for(;*a!='\0';a++)
        ;
    tag+=Judge(--a);
    for(;*b!='\0';b++)
        ;
    tag+=Judge(--b);    
    if(tag==2)
        return false;
    else
        return true;
}

我来回复

您尚未登录,请登录后再回复。点此登录或注册