题目:
有n个物品,A和B开始取物品,A先手,先手先取k(1≤k≤n−1),这个k先手随便选,然后后手也取k个,之后每个人都只能取k个,如果谁刚好取完了最后的一部分,谁就赢了,如果最后有剩余并且小于k个,就没人能取完,那么就是平局。
假设每个人都是绝对聪明的,你能判断A能赢吗?如果A能赢,A尽量赢,否则能平尽量平,迫不得已才输。
物品数n:[ 1, 10^10 ]
思路:
三种情况
如果 n = 2 ,那么先手必输
如果 n 是奇数,那么先手必赢(k取1即可)
如果 n 是偶数:(1)如果n是2的次方数,那么先手必不能赢,但是先手取n-1即可平手; (2)否则,一定能赢。
Let’ s think about it seriously:
首先我们可以理解 n 是奇数时先手必赢的情况。
我们想:整数n分解质因子,如果质因子里有一个奇数 x ,那么 n = x * (n / x),那么就又回到了n是奇数的情况——先手必赢。
我们知道质数只有2一个偶数,所以整数 n 有且只有一个质因子为 2 的时候(也就是n为2的次方数时)只能打平,赢不了。【这里我用了先将n对2取对数为m(向下取整),然后再求2^m == n ? 如果等于即n为2的次方数】
那么剩下的就是一定能赢的情况了。
Code:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <list>
#include <map>
#define INF 0x3f3f3f3f
#define MID l + r >> 1
#define lsn rt << 1
#define rsn rt << 1 | 1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
using namespace std;
typedef long long ll;
typedef vector<int>:: iterator VITer;
const int maxN=1e5+5;
ll log2_ll(ll x)
{
ll ans = 0;
while(x >>= 1) ++ ans;
return ans;
}
ll fast_power(ll x, ll y)
{
ll base = x, ans = 1;
while(y)
{
if( y & 1 )
ans *= base;
base *= base;
y >>= 1;
}
return ans;
}
int main()
{
ll T; scanf("%lld", &T);
while(T--)
{
ll n; scanf("%lld", &n);
if( n == 2 )
{
printf("NO\n");
continue;
}
else if( n & 1 )
{
printf("YES\n");
continue;
}
else
{
if(fast_power(2,log2_ll( n ) ) == n)
printf("PING\n");
else
printf("YES\n");
continue;
}
}
return 0;
}