Multiplication Game (RMRC2017) (c++) (质因数分解)

问题 E: Multiplication Game

时间限制: 5 Sec   内存限制: 128 MB
提交: 256   解决: 59
[提交][状态][讨论版][命题人: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

提示



题目大意就是对于所给定的数N,Alice或者Bob可以选择他的质因子,每次选择后将从1开始的数M乘以所选择的质因子,到最后谁使得M==N谁赢,若M>N,则输出tie。

例如:

10 Alice 这组样例

10 = 2 * 5 ,先手为Alice,若Alice选2此时M=1*2 = 2 ,Bob可选5,此时M=2*5=10=N;若Alice选5,此时M=1*5=5,Bob可选2,此时M=5*2=10=N,即此种情况无论先手选取哪一个,后手必赢;


30 Alice 这组样例

30 = 2 * 3 * 5 ,先手为Alice ,无论Alice选哪一个,Bob都可跟选,使M出现大于N的情况,此时tie;


50 Alice 这组样例

扫描二维码关注公众号,回复: 2332802 查看本文章

50 = 2 * 2 * 5 ,先手为Alice ,Alice保证自己赢则必须先取2,此时先手有必胜策略;


100 Bob 这组样例

100 = 2 * 2 * 2 * 5 , 先手为Bob,若Bob选2,Alice为了导致tie不发生,则必须选2,此时可看出无论Bob接下来选什么,Alice都会获胜,此时后手有必胜策略;


观察可知:

若质因子种类个数大于3,则必定会出现tie的情况;若质因子种类等于1,则先手必赢;

若质因子种类个数等于2,{

            若质因子1个数减质因子2个数的差等于1,则先手有必胜策略;

            若质因子1个数减质因子2个数的差等于0,则后手有必胜策略;

            除此之外则出现tie;


代码如下:

#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
 
using namespace std;
 
const int MAXN = 100005 ;
int a[MAXN] ;        ///保存质因子的种类
int b[MAXN] ;        ///保存某个质因子的系数,也就是某种质因子有多少个
 
void Fac( int num , int &tot ){        //分解质因数模版
    tot = 0 ;                          ///记录质因子个数
    int now = num ;
    if ( now % 2 == 0 ){               ///略微加速
        a[++tot] = 2 ;
        b[tot] = 0 ;
        while ( now % 2 == 0 ){
            ++ b[tot] ;
            now /= 2 ;
        }
    }
    for ( int i = 3 ; i <= sqrt(num) ; i += 2 ){        ///略微加速
        if ( now % i == 0 ){
            a[++tot] = i ;
            b[tot] = 0 ;
            while ( now % i == 0 ){
                ++ b[tot] ;
                now /= i ;
            }
        }
    }
    if ( now != 1 ){
        a[++tot] = now ;
        b[tot] = 1 ;
    }
//        for ( int i = 1 ; i <= tot ; i ++ ){
//        cout << a[i] << " " << b[i] << endl ;
//    }
    return ;
}
 
int main(){
    int t ;
    scanf("%d" , &t) ;
    while ( t -- ){
        int n ;
        char str[10] ;
        scanf("%d %s" , &n , str) ;
        int tot ;
        Fac( n , tot ) ;
        if ( tot >= 3 ){
            printf("tie\n") ;
        }else if ( tot == 2 ){
            if ( abs(b[1] - b[2]) == 1 ){
                puts(!strcmp(str , "Alice") ? "Alice" : "Bob" ) ;
            }else if ( abs(b[1] - b[2]) == 0 ){
                puts(!strcmp(str , "Alice") ? "Bob" : "Alice" ) ;
            }else{
                puts("tie") ;
            }
        }else{
            if(b[1] % 2 == 1){
                puts(!strcmp(str , "Alice") ? "Alice" : "Bob" ) ;
            }
            else{
                puts(!strcmp(str , "Alice") ? "Bob" : "Alice" ) ;
            }
 
        }
    }
    return 0 ;
} 

以上代码4216ms,卡时间通过

若分解质因数代码如下则会超时:

void Fac( int num , int &tot ){
    tot = 0 ;
    int now = num ;
    for ( int i = 2 ; i <= sqrt(num) ; i ++ ){
        if ( now % i == 0 ){
            a[++tot] = i ;
            b[tot] = 0 ;
            while ( now % i == 0 ){
                ++ b[tot] ;
                now /= i ;
            }
        }
    }
    if ( now != 1 ){
        a[++tot] = now ;
        b[tot] = 1 ;
    }
    return ;
}

感谢dalao的指点ヾ(o◕∀◕)ノヾ

猜你喜欢

转载自blog.csdn.net/colpac/article/details/80154132