2187944 | 2007-01-01 19:14:20 | Accepted | 1893 | C++ | 00:00.00 | 388K | Crux.D |
这题好X难。
题目大概意思是:两人轮流乘一个2-9的数,从1开始乘,求谁的乘积先大于N。
如果是加法就好做了。凑到剩下的数能整除11,然后对称着加。问题是乘法。
所以寻找必胜点(段)。以1000为例。
1000 | 999 ... 112 | 若占住999到112,则对手必胜。必须让对手占领此段。
1000 | 999 ... 112 | 111 ... 56 | 因此必占段是 111 -? 。如果56被对手占住,则56×2=112,入必败段。问题转化成为占56。
如此循环。如下 1000 | 999 ... 112 | 111 ... 56 | 55 ... 7 | 6 ... 4 | 3 ... 1
仔细考虑端点,我在处理端点情况时想了好久。
这是牛人的代码。
#include <stdio.h>
unsigned int N;
bool StanWins ()
{
// printf ( "%u\n" , N );
if ( N == 1 ) return true;
int step;
for ( step = 1; N > 1; step ++ )
if ( step & 1 ) N = ( N - 1 ) / 9 + 1;
else N = ( N + 1 ) / 2;
return ( step & 1 ) == 0;
}
int main()
{
// freopen ( "p.in" , "r" , stdin );
while ( scanf ( "%u" , &N ) != EOF )
if ( StanWins () ) printf ( "Stan wins.\n" );
else printf ( "Ollie wins.\n" );
return 0;
}
这是我的代码。
#include <cstdio>
unsigned int n;
int main()
{
//freopen("in.txt", "r", stdin);
while(scanf("%u", &n) != EOF)
{
int step = 0;
//printf("%u\n", n);
if(n == 1)
{
printf("Stan wins.\n");
continue;
}
while(n > 1)
{
n = (n - 1) / 9 + 1;
step ++;
if(n <= 1) break;
n = (n + 1) / 2;
step --;
}
if(step)
printf("Stan wins.\n");
else
printf("Ollie wins.\n");
}
return 0;
}
评论