CF78C题解
原题
思路概述
题意分析
简单博弈论水题。给定 \(n\) 条长为 \(m\) 的木棍,Timur与Marsel两只海狸从中轮流将一条木棍分为任意等分且要保证等分出的木棍长度 \(len≥k\) ,且Timur先手。最先无法操作的判为失败,求谁必胜。
思路分析
考虑本题数据规模 \(n,m,k∈[1,10^9]\) ,不可能DP打表,直接往结论题方向思考。
算法实现
\(n\) 为偶数的情况
对于 \(\frac{n}{2}∈N^*\) 的情况,无论先手方采取任何措施,后手方只需要模仿先手方操作即可。由于一次只能操作一条木棍,所以当先手方将一条木棍切分到不可分时,后手方也可以将另一条木棍切分到不可分。以此类推,最终必然是后手方切分完最后一条木棍,先手方必败。
\(n\) 为奇数的情况
根据博弈论常识不难知道,一个必胜态当且仅当可以在自己操作的一步内将状态转移为必败态。
所以对于 \(\frac{n}{2}∉N^*\) 的情况,先手方是否有必胜策略的条件即为能否在一步内将一条木棍切为不可分的状态,即将状态转移为 \(n\) 为偶数的情况。
对长度 \(m\) 进行因子分解,若 \(m\) 存在一个因子 \(p\) 满足 \(p≠1 \text{ and } \frac{m}{p}≥k\) ,则说明先手方可以将一条木棍等分为 \(\frac{m}{p}\) 份,将这条木棍分为不可再分的状态。切分后状态为必败态,故此时先手方必胜,反之必败。
由上文就得到了本题的判断函数(设函数值为 \(1\) 则必胜,反之必败)如下:
\[f(x)=\begin{cases}1,\frac{n}{2}∉N^*\text{ and }∃p,p≠1 \text{ and } \frac{m}{p}≥k\\0,\text{otherwise} \end{cases}
\]
AC code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<set>
#include<ctime>
#define RI register int
using namespace std;
int n,m,k;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);
cin >> n >> m >> k;
if(n&1 && k<=m)/*n为奇数且k≤m时 才有必胜态的存在可能*/
{
for(RI i=1,lim=(int)sqrt(m)+1;i<=lim/*也可以写成i*i<=m 但速度稍慢*/;++i)
if(!(m%i) && ((i>=k && m/i>1) || (m/i>=k && i>1)))
{
/*对于m存在因子i满足i≠1且m/i≥k或i≥k 则Timur可以第一轮就将状态改变为偶数条木棍 即必败态*/
puts("Timur");
return 0;
}
puts("Marsel");
}
else puts("Marsel");
return 0;
}
浙公网安备 33010602011771号