ZOJ-3599 Game (博弈 K倍动态减法)

Game Time Limit: 3 Seconds       Memory Limit: 65536 KB

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.

Input

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)

Output

For each test case output the number of positive integers Alice can choose for n to make her win the game.

Sample Input

3
1 10
2 10
3 10

Sample Output

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;
}


你可能感兴趣的:(博弈,k倍动态减法)