Alice and Bod decide to play a new stone game. At the beginning Alice puts n(n>1) stones (out of N in all) on the table. Alice and Bob remove the stones in turn. At each step the player should remove some number of stones. The number of stones the player removed should be at least one, and cannot exceed m times of the number of stones the player removed at the last step. The player who removes the last stone wins the game. Alice always plays first and of course at the first turn, she cannot remove all the stones. Alice wants to know how many positive integers nshe can choose to win the game if both players play optimally.
Since you're an ace programmer, Alice wants you to help her.
There are multiple test cases. The first line of input contains an integer T (0 < T ≤ 500) indicating the number of test cases. Then T test cases follow.
Each test case is a line of 2 integers m and N(0 < m ≤ 2012, 1 < N < 231)
For each test case output the number of positive integers Alice can choose for n to make her win the game.
3 1 10 2 10 3 10
6 5 4
思路:
博弈K倍动态减法的一个变形,k倍动态减法详见 http://blog.csdn.net/tbl_123/article/details/24884861
题意大概是先手先从N个中选出n(n < N)个,两人轮流从n中取,遵循k倍动态减法的规则,若要保证先手必赢,问n有几种选法;
这里我们只需找出构造的数列中比N小的数的个数(即0...N中必败态的个数),再另N-i或N-i-1,即为先手可以选出得个数了
代码:
#include <stdio.h> #define N 3000000 long long a[N], b[N]; int main() { long long n; int k, loop = 0, casei = 1; scanf("%d", &loop); while(loop --){ scanf("%d%lld", &k, &n); a[0] = b[0] = 1; int i = 0, j = 0; while(n > a[i]){ i ++; a[i] = b[i - 1] + 1; while(a[j + 1] * k < a[i]) j ++; if(k * a[j] < a[i]) b[i] = b[j] + a[i]; else b[i] = a[i]; } if(n == a[i]) printf("%lld\n", n - i - 1); else printf("%lld\n", n - i); } return 0; }