您的位置:首页 > 其它

【u206】最大赢家

2017-10-06 19:23 225 查看

Time Limit: 1 second
Memory Limit: 128 MB

【问题描述】

Nic和Susan在玩一个有趣的游戏:在游戏开始前,他们先约定一个正整数n,同时令m=1。游戏过程中,每个人都可以将m的值扩大2到9中的 
任意倍数。第一个使得m≥n的人就是最后的赢家。 
假设Nic和Susan都十分聪明,并且游戏过程中都使用最佳的策略,问谁会是最后的赢家(Nic总是第一个先玩)。 


【输入格式】

一个正整数n(1≤n≤2^32-1)。

【输出格式】

在使用最佳的策略的情况下,如果Nic必胜,则输出“Nic”。如果Susan必胜,则输出“Susan”。否则输出“God”。

【数据规模】

Sample Input1

9

Sample Output1

Nic
【题解】 等价题意如下
给定N,Nic和Susan轮流将N整除2~9,第1个使N<=1的人赢。
Nic先手,问对于给定的N谁必胜。谁必胜 设f
表示N为n时是先手赢还是先手输。 转移 假设x ∈{2,3,4,5,6,7,8,9}; 如果n/x为整数。则M=n/x否则M= (n / x)+1 这里的除法是整除运算。直接去尾。 然后f
= f
|| !f[M]; 我们这里的讲解围绕那个等价题意展开。 F[1..9]都为true表示Nic只要除一下就能<=1了。所以是先手赢。 然后我们对F[t]考虑。 如果f[t/x](这里的x∈上面那个区间)是先手输。也就是说先手从t/x开始会输。 那么我们只要让t/x变成t就好了,然后就变成先手赢了。 因为你是t。然后除一个x就变成t/x了。然后先手就不是nic了。而是Susan.而f[t/x]==true表示在t/x时先手(这下变成Susan)一定会输。那不就等价为f[t]是先手(nic)赢了吗? 根据这样的规律我们可以写出以下程序 (注意:下面这个程序不足以过所有的数据); memset(bo, false, sizeof(bo));
for (int i = 1; i <= 9; i++)
{
bo[i] = true;
}
for (int i = 10; i <= 21999999; i++)
for (int j = 2; j <= 9; j++)
{
int mm;
if ((i %j) == 0)
mm = i / j;
else
mm = (i / j) + 1;
if (!bo[mm])
bo[i] = true;
}
然后我们用这个程序求出bo[1..2000]的值。进而可以发现规律 —n =[1, 9],先手必胜 —n =[10, 18],先手必败即后手必胜 —n =[19, 162],先手必胜 —n =[163, 324],先手必败即后手必胜 也就是先手胜i = 9 if (n<=9) 先手 后手胜i=i*2 if (n <=i) 后手 先手胜i=i*9 if (n <=i) 先手 后手胜i=i*2 if (n <= i)后手 i会很大 ,要用long long 。。。 【代码】
/*
等价题意如下
给定N,Nic和Susan轮流将N整除2~9,第1个使N<=1的人赢。
Nic先手,问对于给定的N谁必胜。

*/
#include <cstdio>

long long n;

int main()
{
scanf("%lld", &n);
long long i = 9; //一开始i == 9然后小于9就是先手胜
int b = 1;
while (b != 2) //这个条件是不可能实现的 。所以就一直循环。
{
if (n <= i) //如果在我们找到的规律区间里就输出相应的答案 然后结束循环
{
if (b == 1)
printf("Nic\n");
else
printf("Susan\n");
break;
}
if (b == 1) //如果现在是先手胜的区间那么就直接*2
i = i * 2;
else //否则乘9;
i = i * 9;
b = 1 - b;
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: