学习笔记-2024第15届蓝桥杯试题python:砍柴

试题E:砍柴
【问题描述】
小蓝和小乔正在森林里砍柴,它们有T 根长度分别为n1,n2,…, nT 的木头。对于每个初始长度为n 的木头,小蓝和小乔准备进行交替砍柴,小蓝先出手。每次砍柴时,若当前木头长度为x ,需要砍下一截长度为p 的木头,然后换另一个人继续砍,其中2 ≤ p ≤ x 且p 必须为质数。当轮到某一方时x = 1 或x = 0 ,它就没法继续砍柴,它就输了。它们会使用最优策略进行砍柴。请对每根木头判断是小蓝赢还是小乔赢,如果小蓝赢请输出1 (数字1),如果小乔赢请输出0 (数字0)。

【输入格式】
输入的第一行包含一个正整数T,
接下来T 行,每行包含一个正整数,其中第i 的整数为ni 。

【输出格式】
输出T 行,每行包含一个整数,依次表示对于每一根木头的答案。

【样例输入】
3
1
2
6

【样例输出】
0
1
1

import math
# 筛法预处理得到范围内所有质数
def get_primes(max_val):
    v = [True] * (max_val + 1)
    for x in range(2, max_val + 1):
        if not v[x]:
            continue
        for y in range(x * 2, max_val + 1, x):
            v[y] = False
    primes = [x for x in range(2, max_val + 1) if v[x]]
    return primes

# DFS 博弈
def win(x):
    if memo[x] != 0:
        return memo[x] == 1
    if x <= 1:
        return False
    # 剪枝: 倒序遍历质数集, 更快接近 DFS 基态
    for i in range(bis(x), -1, -1):
        if not win(x - primes[i]):
            memo[x] = 1
            return True
    memo[x] = -1
    return False

# 二分, 从质数集中查找 <= x 的最大位置
def bis(x):
    l = 0
    r = len(primes)
    while l < r:
        m = (l + r) // 2
        if primes[m] <= x:
            l = m + 1
        else:
            r = m
    return l-1

T = int(input())
woods = [int(input()) for _ in range(T)]

max_wood = max(woods)
primes = get_primes(max_wood)
memo = [0] * (max_wood + 1)

for wood in woods:
    result = 1 if win(wood) else 0
    print(result)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值