• 【uoj#51】[UR #4]元旦三侠的游戏 博弈论+dp


    题目描述

    给出 $n$ 和 $m$ ,$m$ 次询问。每次询问给出 $a$ 和 $b$ ,两人轮流选择:将 $a$ 加一或者将 $b$ 加一,但必须保证 $a^ble n$ ,无法操作者输,问先手是否必胜。

    $nle 10^9$ ,$mle 10^5$ ,$age 2$ ,$bge 1$ ,$a^ble n$


    题解

    博弈论+dp

    显然可以想到预处理 $f[i][j]$ 表示 $a$ 为 $i$ ,$b$ 为 $j$ 时先手能否胜利。显然由 $f[i+1][j]$ 和 $f[i][j+1]$ 推出。

    但是由于 $n$ 有 $10^9$ 就会GG...

    我们考虑:当 $i^jle n$ 且 $i^{j+1}>n$ 时,先手只能选择将 $a$ 加一,后手也一样。因此胜负已定。

    因此当 $b=1$ 时可以只预处理到 $f[sqrt n][1]$ ,当 $a>sqrt n$ 时显然可以 $O(1)$ 判断。

    时间复杂度 $O(m+sqrt nlog n)$ 。

    其实对于每一个 $b$ 都可以用同样的方法判断,时间复杂度变为 $O(m+sumlimits_{i=2}^{log n}sqrt[i]{n})=O(m+sqrt n)$ 但没什么必要。。。

    #include <cstdio>
    int p[32010][31] , log[32010] , f[32010][31]; //0: win
    int main()
    {
    	int n , m , i , j , a , b;
    	scanf("%d%d" , &n , &m);
    	for(i = 2 ; i <= 32000 ; i ++ )
    	{
    		if(i > n) log[i] = 0;
    		else
    		{
    			p[i][1] = i;
    			for(j = 2 ; 1ll * p[i][j - 1] * i <= n ; j ++ )
    				p[i][j] = p[i][j - 1] * i;
    			log[i] = j - 1;
    		}
    	}
    	f[32001][1] = !((n - 32001) & 1);
    	for(i = 32000 ; i != 1 ; i -- )
    		for(j = log[i] ; j ; j -- )
    			f[i][j] = !(f[i][j + 1] || f[i + 1][j]);
    	while(m -- )
    	{
    		scanf("%d%d" , &a , &b);
    		puts((a > 32000 ? !((n - a) & 1) : f[a][b]) ? "No" : "Yes");
    	}
    	return 0;
    }
    
  • 相关阅读:
    读財报:交易额增长111%的京东,为毛还是亏?
    HDU 1548 A strange lift 搜索
    linux两台server远程copy文件
    Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离具体解释
    js事件防止冒泡
    LeetCode Rotate Array
    ARM架构授权和IP核授权有什么不一样啊?
    Linux系统结构 详解
    mount -o
    ARM开发板系统移植-----u-boot的编译
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/8244562.html
Copyright © 2020-2023  润新知