Multiplication Game

题目描述

Alice and Bob are in their class doing drills on multiplication and division. They quickly get bored and instead decide to play a game they invented.

The game starts with a target integer N≥2, and an integer M = 1. Alice and Bob take alternate turns. At each turn, the player chooses a prime divisor p of N, and multiply M by p. If the player’s move makes the value of M equal to the target N, the player wins. If M > N, the game is a tie.

Assuming that both players play optimally, who (if any) is going to win?

输入

The first line of input contains T (1≤T≤10000), the number of cases to follow. Each of the next T lines describe a case. Each case is specified by N (2≤N≤231-1) followed by the name of the player making the first turn. The name is either Alice or Bob.

输出

For each case, print the name of the winner (Alice or Bob) assuming optimal play, or tie if there is no winner.

样例输入

10

10 Alice

20 Bob

30 Alice

40 Bob

50 Alice

60 Bob

70 Alice

80 Bob

90 Alice

100 Bob

样例输出

Bob

Bob

tie

tie

Alice

tie

tie

tie

tie

Alice

博弈论的问题,就是对于N来说,所有的质因数的乘积一定等于他本身,这道题的意思就变成了每个人取一个质因数谁先把所有的质因数取尽谁就赢。这里的质因数的数量是指总数,如18的质因数有2,3,3,有3个。如果其本身就是一个质因数,则其质因数的数量为1。答案很明显了,其个数为奇数,先手必胜,偶数,先手必败。但是有一个关键的问题,这个游戏的操作者可以使游戏成为平局状态,也就是可以使所得的M比N大,比如30,其质因数为2,3,5,无论先手取哪一个,后手只要和先手取一样的数,都可以使游戏成为平局状态,对于必败方而言,只要自己的可操作的总数比出现次数最少的那个质因数多的话,败方就可以把游戏状态从失败变成平局“tie”,但胜方不会这么做,所以这个处理一定是对败方才进行的,而且胜方为了阻止败方把游戏变成平局,一定会选取出现次数最多的那个质数,比如18,如果先手(胜方)选取2的话,后手再拿一个2就变成平局了,这不是胜方希望看到的。而对于先手操作状态即是初始状态,但后手操作状态一定是先手拿过一次后的状态。回到刚才所说的败方要把状态变成平局的问题,先手操作就是对初始状态操作即可,但后手就要对先手拿过一次后的状态进行处理,N的质因数为奇数时先手必胜,后手要把游戏变成平局,N为偶数时,先手要把游戏状态变成平局。双方的可操作数都是(质因数总数/2),只要比一下可操作数与质数最小的出现次数,谁更大,即可判断是否可能平局。

#include <bits/stdc++.h>
#include <map>
using namespace std;
map <string,int> A;
map<int,int> B;
int prime[100005];
int s,num;
void PrimeDecomposition(int k)
{
    if(k<2) ;
    else if(k==2)
    {
        prime[s]=2;
        B[2]=1;
        num++;
    }
    else
    {

        for(int i=2; i<=sqrt(k); i++)
        {
            while(k>=i)
            {
                if(k%i==0)
                {
                    num++;
                    if(!B[i]) prime[s++]=i;
                    B[i]++;
                    k=k/i;
                }
                else
                    break;
            }
        }
        if(k!=1)
        {
            if(!B[k])
            {
                num++;
                prime[s++]=k;
            }
            B[k]++;
        }
    }
}
int main()
{
    A["Alice"]=1;
    A["Bob"]=2;
    A["tie"]=3;
    int t,n;
    string tmp;
    cin>>t;
    while(t--)
    {
        cin>>n>>tmp;
        int mark=A[tmp];
        memset(prime,0,sizeof(prime));
        B.clear();
        s=0;
        num=0;
        PrimeDecomposition(n);
        //cout<<num<<' '<<s<<endl;
        //for(int i=0; i<s; i++)
        //cout<<prime[i]<<' '<<B[prime[i]]<<endl;
        int mini=100005,ans,maxi=0,m;
        if(num%2==1){
        for(int i=0;i<s;i++)
        {
            if(B[prime[i]]>maxi)
            {
                maxi=B[prime[i]];
                m=prime[i];
            }
        }
        B[m]--;
        }
        for(int i=0; i<s; i++)
        {
            if(B[prime[i]]<mini)
                mini=B[prime[i]];
        }
        ans=num/2;
        //cout<<mini<<' '<<ans<<endl;
        if(mini<ans)
        {
            cout<<"tie"<<endl;
            continue;
        }
        if(num%2==0)
        {
            if(mark==1)
            {
                cout<<"Bob"<<endl;
                continue;
            }
            if(mark==2)
            {
                cout<<"Alice"<<endl;
                continue;
            }
        }
        if(num%2==1)
        {
            if(mark==2)
            {
                cout<<"Bob"<<endl;
                continue;
            }
            if(mark==1)
            {
                cout<<"Alice"<<endl;
                continue;
            }
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/shadowlink/p/8942901.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值