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


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值