牛客竞赛 15867 A game(博弈论)

原题链接:
https://ac.nowcoder.com/acm/problem/15867
题意:
有n根长度为m的棍子,两个人轮流切这些棍子,只有一根棍子的可以被平均切成至少两段且长度为整数且长度大于等于k,才可以算作可被切,被切过的棍子可再次被当作是棍子(如果可以被切)。轮到某人且此时没有可以切的棍子,那么此人输掉比赛。

题解 :
(1)如果n为偶数:
·那么Macle必败,因为tony只需要模仿Macle的每一步,那么最终必然Macle没有棒子可以去切。
(2)如果n为奇数:
·那么只要初始的棍子可以被切,那么Macle 可以将其中一个棍子切成不可以再操作的棍子,之后相当于棍数减一,变为 偶数,而此时是Tony先手,那么如上所述,先手必败。
·如果初始的棍子无法被切,那么从一开始Macle就无法操作,Tony获胜

AC代码(此题数据较弱,有一种有漏洞的做法也可以过):

#include <bits/stdc++.h>

using namespace std;

#define LL long long
#define Re register
#define U unsigned
#define forn(i,a,b) for(Re int i = a;i <= b;++i)
#define nfor(i,a,b) for(Re int i = a;i >= b;--i)
#define CLR(i,a) memset(i,a,sizeof(i))
#define BR printf("--------------------\n")
#define pb push_back
#define Rep(i,a,b) for(int i=a;i<=b;i++)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
const double PI=atan(1.)*4.;
const int maxn=1e6+5;
const int inf = 0x3f3f3f3f;
const int mod=1e9+7;
const double e=2.71828182845904523536;
int dir[4][2]={1,0,0,1,-1,0,0,-1};

int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);
   	cout.tie(0);
    int n,m,k;
    cin>>n>>m>>k;
    if(n%2==0)//n为偶数则tony必赢,因为tony只需要和Macle 做同样的事,那么最终一定是macle 输
    {
        cout <<"Tony\n";
        return 0;
    }
    else
    {
        int z=m/k;//计算一根棒子能切成长度大于等于k的段数
        bool ok=false;
        for(int i=z;i>=2;i--)
        {
            if(m%i==0&&(i>=k||m/i>=k))//找到一个能够满足平均长度大于等于k,且可以切至少2段的情况
            {
                ok=true;
                break;
            }
        }
        if(ok)//可以切成多段,且长度大于k,macle只要切掉一个,并且此根棒子不可以再切,则相当于少了一根棒子,tony先手
        {
            cout<<"Macle\n";
        }
        else//初始的时候无法切,则tony直接获胜
        {
            cout<<"Tony\n";
        }
    }
	return 0;
}

含有漏洞的做法:

#include <bits/stdc++.h>

using namespace std;

#define LL long long
#define Re register
#define U unsigned
#define forn(i,a,b) for(Re int i = a;i <= b;++i)
#define nfor(i,a,b) for(Re int i = a;i >= b;--i)
#define CLR(i,a) memset(i,a,sizeof(i))
#define BR printf("--------------------\n")
#define pb push_back
#define Rep(i,a,b) for(int i=a;i<=b;i++)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
const double PI=atan(1.)*4.;
const int maxn=1e6+5;
const int inf = 0x3f3f3f3f;
const int mod=1e9+7;
const double e=2.71828182845904523536;
int dir[4][2]={1,0,0,1,-1,0,0,-1};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,m,k;
    cin>>n>>m>>k;
    if(n%2==0)
    {
        cout <<"Tony\n";
        return 0;
    }
    else
    {

        int z=m/k;
        if(m%z==0&&z!=1)//漏洞:不是一定分为z棍子
        {
            cout<<"Macle\n";
        }
        else
        {
            cout<<"Tony\n";
        }
    }
    return 0;
}

漏洞测试数据:
1 14 4

欢迎评论!

猜你喜欢

转载自blog.csdn.net/wjl_zyl_1314/article/details/95967253