http://acm.timus.ru/problem.aspx?space=1&num=1023
题目大意
给定 K(3≤K≤108) 个石子,一次最多取 L(2≤L<k) 个石子,问L最小取多少能使后手必胜。
背景
正如你所知道的,Yekaterinburg市夺得了2032年夏季奥运会的举办权。这允许作为比赛举办国的俄国能够修改一些比赛项目。所以为了提升command result(?),俄国决定把体操项目换成一个全新的比赛项目”Buttons”。
新游戏的规则很简单,有一堆共K个纽扣,2个参赛者。2个人轮流从这堆纽扣中取走一些纽扣(最少1个,最多L个),最后取完纽扣的人获胜。作为奥林匹克比赛项目,这个游戏的规则难度加大了,比赛先手(即第一个取纽扣的人)有机会决定
K(3≤K≤108)
(不要问我哪来这么多纽扣)。比赛后手(即第二个取纽扣的人)可以决定
L(2≤L<K)
。
问题
你的团队接受了一个很艰巨的任务:写一个程序帮助后手对于已经给定的K,找出最小的L使得可以保证后手必胜。
比如如果一开始只有
K=3
个纽扣,那么令
L=2
时,无论先手取1个还是取2个,后手都能获得胜利(取2个或者取1个)。
输入
输入一行一个整数K。
输出
输出一行一个整数L。
样例输入(K)
3
样例输出(L)
2
题解
考虑
K=L+1
的情况,这种情况下先手无论拿多少个石子(
1..L
),都能剩下不超过
L
个石子让后手直接全部拿完。
如果我们构造一轮又一轮的这样的步骤,即
那么问题就变成了找到
K
的最小的大于2的因数,减一就是
#include <cstdio>
int factor[N];
int main() {
int n, factor, i;
scanf("%d", &n);
// L must be larger than 2, so factor must be larger than 3.
if (n % 2 == 0 && n / 2 > 2)
factor = n / 2;
else
factor = n;
for (i = 2; i * i <= n; ++i)
if (n % i == 0) {
factor = i;
break;
}
--factor;
printf("%d\n", factor < 2 ? 0 : factor);
return 0;
}