Codeforces 78C Beaver Game(数论、博弈)

Codeforces 78C Beaver Game(数论)

链接:http://codeforces.com/problemset/problem/78/C


题目

Time Limit:1000MS Memory Limit:262144KB
Description
Two beavers, Timur and Marsel, play the following game.

There are n logs, each of exactly m meters in length. The beavers move in turns. For each move a beaver chooses a log and gnaws it into some number (more than one) of equal parts, the length of each one is expressed by an integer and is no less than k meters. Each resulting part is also a log which can be gnawed in future by any beaver. The beaver that can’t make a move loses. Thus, the other beaver wins.

Timur makes the first move. The players play in the optimal way. Determine the winner.

Input
The first line contains three integers n, m, k (1 ≤ n, m, k ≤  109 ).

Output
Print “Timur”, if Timur wins, or “Marsel”, if Marsel wins. You should print everything without the quotes.

Sample Input
1 15 4
Sample Output
Timur
Sample Input
4 9 5
Sample Output
Marsel


题意

有n个木棍,每个木棍长m,现在让两个人轮流切木棍,要求每小段不能短于k,且每次只能切同一条木棍。最后不能切的人输,博弈问题


分析

首先针对木棍条数分情况:
偶数根:后手必胜,因为后手只需要模仿先手的处置方法,就一定会胜利。
奇数根:(1)若能切割:若能切割的话。令先手的第一次处置是完全切割一根,剩下的问题就转化成了当前后手为“先手“的偶数次情况。即先手必胜。
(2)若无法切割,则先手直接输。
故问题转化成了判断是否偶数根和奇数根时先手是否能做第一次处置的问题。

优化:求先手第一次能否切割,直接i从0到sqrt(m)即可。
易错点 :遍历时对于m%i != 0的情况,要跳出,不进行判断(原因:对于长度17、最短长5的木头,当i为6时,没有这句判断将使程序忽略掉5的模。但是模掉的长度也许可以单独取一次,比如此情况时切割为6-6-5三段的取法是可行的)


源码

//数论+博弈
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<string>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<utility>
#include<sstream>
#define mem0(x) memset(x,0,sizeof x)
#define mem1(x) memset(x,1,sizeof x)
#define mem11(x) memset(x,-1,sizeof x)
#define dbug cout<<"here"<<endl;
//#define debug

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x7fffffff;
const int MAXN = 1e6+10;
const int MOD = 1000000007;

int main(){
    #ifdef debug
        freopen("C:\Users\asus-z\Desktop\input.txt","r",stdin);
        freopen("C:\Users\asus-z\Desktop\output.txt","w",stdout);
    #endif
    int n,m,k;
    cin >> n >> m >> k;
    bool secondWin = 1;
    if(n%2 == 0){
        secondWin = 1;
    }
    else{
        for(int i = 1; i < sqrt(m)+1; ++i){
            if(m%i != 0)                //(必要)此句非剪枝,去掉此判断会出错
                continue;
                /**EG:对于长度17、最短长5的木头,当i为6时,没有这句判断将使程序忽略掉5的模,
                *   但是模掉的长度可以单独取一次,即6-6-5的取法是可行的
                */
            if(i>=k && m/i>1){          //此判断为针对切割之后的每节长度进行的判断
                secondWin = 0;
                break;
            }
            else if(i>1 && m/i>=k){     //此处为针对切割次数进行的判断
                secondWin = 0;
                break;
            }
        }
    }
    if(secondWin)
        cout << "Marsel" << endl;
    else
        cout << "Timur" << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值