Multiplication Game(博弈GAME,质因子分解)

34 篇文章 0 订阅
2 篇文章 0 订阅

5121: Multiplication Game

时间限制: 5 Sec   内存限制: 128 MB
提交: 158   解决: 33
[ 提交][ 状态][ 讨论版][命题人: admin]

题目描述

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

提示

来源

RMRC2017 


题意:给定一个n,A和B选择一个人先手,每次选择n的一个质因子,让M乘上这个质因子(M初始为1),谁能使M等于n则获胜,若M>n则输出 tie。

题解:首先n的质因子的数量是一定的,若要使M==n,那么必定要按照n的各个质因子的实际数量去拿才行,若按照这种方案,则开始即是奇异局势,设n中质因子的数量为num,当num为偶数时,后手必胜,那么先手必要去打破平衡,使得先手的策略一定是不按照能凑出来n的方案去拿,使得M>n,此时先手能选择的质因子数量是num/2,那么若num/2>数量最少的那种质因子的数量,则一定能打破平衡输出tie,否则就是后手必胜。当num为奇数时,先手必胜,那么后手需要去打破平衡,此处没想到很好的判断方案,那么只能去模拟,策略就是先手要避免每种质因子的数量的平衡被打破,那么他每次拿的一定是当前数量最多的那种质因子,而后手则要去拿当前数量最少的那种质因子,模拟判断是否有质因子被拿超了即可。

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<math.h>
#include<queue>
#include<deque>
#include<ctype.h>
#include<map>
#include<set>
#include<stack>
#include<string>
#include<algorithm>
#define INF 0x3f3f3f3f
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define FAST_IO ios::sync_with_stdio(false)
#define mem(a,b) memset(a,b,sizeof(a))
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MAX=1e5+10;
const int mod=1e9+7;
typedef long long ll;
using namespace std;

const int manx=2e6+5;
ll prime[manx],vis[manx],cot,a[manx];

void primeall()
{
    for(int i=2;i<manx;i++)
        if(vis[i]==0)
        {
            prime[++cot]=i;
            for(int j=i*2;j<manx;j+=i) vis[j]=1;
        }
}

int main()
{
    primeall();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll n;
        scanf("%lld",&n);
        char s[10];
        scanf("%s",s);

        ll num=0,minl=INF,zz=0;
        for(int i=1;prime[i]*prime[i]<=n;i++)
        {
            ll aa=0;
            while(n%prime[i]==0)
            {
                n/=prime[i],aa++;
            }
            if(aa) num+=aa,minl=min(minl,aa),zz++,a[zz]=aa;
        }
        if(n>1) num++,zz++,minl=min(minl,1LL),a[zz]=1;

        if(num%2==0) //后手必胜
        {
            ll temp=num/2;

            if(temp>minl)
                printf("tie\n");
            else if(s[0]=='A')
                printf("Bob\n");
            else
                printf("Alice\n");
        }
        else
        {
            ll temp=num/2;
            if(temp>minl)
            {
                printf("tie\n");
                continue;
            }
            ll flag=0,one=0,two=0;
            while(1)
            {
                sort(a+1,a+1+zz);
                a[zz]--;one++;
                if(a[zz]<0) {flag=1;break;}

                sort(a+1,a+1+zz);
                two++;if(two>temp) break;
                a[1]--;if(a[1]<0) {flag=1;break;}

            }
            if(flag) {printf("tie\n");continue;}

            if(s[0]=='A')
                printf("Alice\n");
            else
                printf("Bob\n");
        }
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值