• 【博弈论】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

    题目大意:两人轮流用所给数的质因数相乘,先达到所给数的人胜利,可出现平局,即某人的决策只能处于必败态则通过操作使博弈编程平局(我不能赢也不让你赢)amazing

    思路分析:根据唯一解定理,质因数是的数目可分为三种情况分析:质因数只有一种、有两种以及大于三种。

        (1)质因数只有一种:该质因数需要奇数个则先手获胜,若需要偶数个则后手获胜;

        (2)质因数有两种:两种质因数所需数目相同,则后手获胜(不论先手如何操作,后手只需平衡即可);

                   两种质因数所需数目不同,if差值为一,则先手获胜;else原必败态可以通过操作使之平局;

        (3)质因数有三种及三种以上:必然可以通过操作使之达到平局。

      1 #include<bits/stdc++.h>
      2  
      3 using namespace std;
      4 const int mod = 1e9+7;
      5 typedef long long ll;
      6 #define LL long long
      7  
      8 const int maxn = 1e5+100;
      9  
     10 int prime[maxn+1];
     11  
     12 bool vis[maxn];
     13 ll cnt;
     14 void primejudge(int n)
     15 {
     16     cnt=0;
     17     vis[1]=true;
     18     ll i,j;
     19     for(i=2; i<=n; i++)
     20     {
     21         if(!vis[i])
     22         {
     23             prime[cnt++]=i;
     24         }
     25         for(j=0; j<cnt&&i*prime[j]<=n; j++)
     26         {
     27             vis[i*prime[j]]=true;
     28             if(i%prime[j]==0)
     29             {
     30                 break;
     31             }
     32         }
     33     }
     34 }
     35  
     36 int main()
     37 {
     38     primejudge(maxn);
     39     int T;
     40     cin>>T;
     41     while(T--)
     42     {
     43         ll n;
     44         string ss;
     45         cin>>n>>ss;
     46  
     47         int ret = 0;
     48         vector<int>v;
     49         for(int i=0; i<cnt; i++)
     50         {
     51  
     52             if(n%prime[i]==0)
     53             {
     54                 ret++;
     55                 int tmp=0;
     56                 while(n%prime[i]==0)
     57                 {
     58                     n/=prime[i];
     59                     tmp++;
     60                 }
     61                 v.push_back(tmp);
     62             }
     63             if(ret>=3)
     64                 break;
     65         }
     66         if(n>1)
     67         {
     68             ret++;
     69             v.push_back(1);
     70         }
     71         if(ret>=3)
     72         {
     73             cout<<"tie"<<endl;
     74         }
     75         else if(ret==1)
     76         {
     77  
     78             if(v[0]%2==0)
     79             {
     80                 if(ss=="Alice")
     81                     cout<<"Bob"<<endl;
     82                 else
     83                     cout<<"Alice"<<endl;
     84             }
     85             else
     86             {
     87                 if(ss!="Alice")
     88                     cout<<"Bob"<<endl;
     89                 else
     90                     cout<<"Alice"<<endl;
     91             }
     92         }
     93         else if(ret==2)
     94         {
     95  
     96             //cout<<" 2 "<<endl;
     97             if(v[1]==v[0])
     98             {
     99                 if(ss=="Alice")
    100                     cout<<"Bob"<<endl;
    101                 else
    102                     cout<<"Alice"<<endl;
    103             }
    104             else
    105             {
    106                 if(abs(v[0]-v[1])==1)
    107                     if(ss!="Alice")
    108                         cout<<"Bob"<<endl;
    109                     else
    110                         cout<<"Alice"<<endl;
    111                 else
    112                 {
    113                     cout<<"tie"<<endl;
    114                 }
    115             }
    116         }
    117         else
    118         {
    119             cout<<ss<<endl;
    120         }
    121     }
    122  
    123 }
    View Code

    注意:这题开始队友wa了几发,一是数据是1e9的线性筛也无法预处理所有质因数,但是可以考虑只预处理1e5内的质数,因为大于1e5之后最多有且只有一个质因数,否则为它本身;

       但在统计质因数时,仍需考虑一种特例,举例说明吧:若说给数为10000019,该数为质数但大于1e5,可直接ret++,但2*10000019,在统计质因数时要先统计2这个因子,然后因为商不等于一,ret++,同时v.push_back(1)。为什么要push呢,因为要比较质因数的出现次数啊,因为这个数大于1e5,所以它之后出现一次,故push_back(1)。

     
  • 相关阅读:
    通过anaconda进行python多版本控制
    搭建java环境
    windows安装 Microsoft Visual c++
    更改jupyter notebook的主题颜色(theme) 包括pycharm
    linux服务器安装anaconda,然后远程使用jupyter
    根据经纬度坐标计算距离-python
    Redis相关链接
    VBA笔记-参考教程
    用sklearn计算卡方检验P值
    linux创建新用户
  • 原文地址:https://www.cnblogs.com/SoulSecret/p/8934480.html
Copyright © 2020-2023  润新知