最开始,我们可以把 n n n 分成三种情况
- 当 n = 1 n=1 n=1,后手赢
- 当 n n n 为奇数,先手赢, n n n 直接除以自身就可以了
前两种情况都比较简单,下面来讨论当 n n n 为偶数的情况
当 n n n 为偶数( 2 2 2 的倍数),想赢的话肯定不能使用减 1 1 1 的操作,因为这样后手必胜。那么就考虑除以约数
由于 n n n 为偶数,我们一定可以将 n n n 分解成一些质数与 2 2 2 的正整数次幂之积 n = p 1 × p 2 × ⋯ × p m × 2 k n=p_1 \times p_2 \times \cdots \times p_m \times 2^k n=p1×p2×⋯×pm×2k ( k > 0 , m ≥ 0 ) (k>0,m \ge 0) (k>0,m≥0),并且满足这些质数都不是 2 2 2 的倍数
又因为每次除掉的值可以是多个质因数的积(只要是约数就行),所以只要 m > 1 m>1 m>1,Ashishgup
就可以很灵活的选择约数。
最后,当 n n n 被除地只剩 2 k 2^k 2k 时,又会有两种情况
- n = 2 n=2 n=2 ,先取的人赢:判断是否能将 m m m 个质数转化成偶数个不为 1 1 1 的数的乘积,如果可以的话说明当前
Ashishgup
可以先取(Ashishgup
获胜) - n > 2 n>2 n>2 ,后取的人赢:判断是否能将 m m m 个质数转化成奇数个不为 1 1 1 的数的乘积,如果可以的话说明当前
Ashishgup
可以后取(Ashishgup
获胜)
否则获胜的就是 FastestFinger
啦
代码
#include<cstdio>
#include<iostream>
using namespace std;
int n;
int main()
{
// freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
if(n==1){
puts("FastestFinger");continue;}
if((n & 1) || n==2){
puts("Ashishgup");continue;}
int tot=0;
for(int i=2;i*i<=n;++i)
if((i & 1) && n%i==0) // 注意这里只能把为奇数的质因数
while(n%i==0)++tot,n/=i;
for(int i=2;i*i<=n;++i)
{
int tmp=n/i;
if((tmp & 1) && n%i==0)
while(n%tmp==0)++tot,n/=tmp;
}
if(n==2)
{
if(tot!=1)puts("Ashishgup");
else puts("FastestFinger"); // 如果只有一个质数的话就不能化为偶数个数之积
}
else
{
if(tot)puts("Ashishgup");
else puts("FastestFinger"); // 这里特判的是0,跟上面原理相同
}
}
return 0;
}