AtCoder abc129

文章讲述了如何使用二进制状态转移和记忆化技术解决一个与斐波那契序列变种相关的问题,涉及计算二进制表示下的和等于1或0的情况,同时考虑取值上限的限制。

C Typical Stairs
斐波那契的变种,有障碍时填0
D Lamp
对每个点维护四个方向可以延伸的最长值
E - Sum Equals Xor
数位dp
f(pos,x,cap)f(pos, x, cap)f(pos,x,cap)
表示在二进制表示下,当前搜索到pos位
因为当前位只有三种可能 (0,0) (1,0) (0,1)
x=1表示(1,0)或者(0,1),即和为1
x=0表示和为0
cap表示之前是否已经达到取值的上限,即如果cap=1,那么必须要考虑和不能超过给定s的值,如果cap=0,那么不需要考虑取值问题
推理见代码

# -*- coding: utf-8 -*-
# @time     : 2023/6/2 13:30
# @author   : yhdu@tongwoo.cn
# @desc     :
# @file     : atcoder.py
# @software : PyCharm
import bisect
import copy
import sys
from sortedcontainers import SortedList
from collections import defaultdict, Counter, deque
from functools import lru_cache, cmp_to_key
import heapq
import math
sys.setrecursionlimit(100010)


def main():
    items = sys.version.split()
    if items[0] == '3.10.6':
        fp = open("in.txt")
    else:
        fp = sys.stdin
    s = fp.readline().strip()
    n = len(s)

    mod = 10 ** 9 + 7
    mem = {}

    def get(pos, x, cap):  # 记忆化TLE
        if pos == n:
            return 1
        if (pos, x, cap) in mem:
            return mem[(pos, x, cap)]
        if cap == 0:
            ret = get(pos + 1, 0, 0) + 2 * get(pos + 1, 1, 0)
        else:
            if s[pos] == '0':
                ret = get(pos + 1, 0, 1)
            else:
                ret = get(pos + 1, 0, 0) + 2 * get(pos + 1, 1, 1)
        return ret % mod

    dp = [[[0] * 2 for i in range(2)] for j in range(n + 1)]
    for i in range(2):
        for j in range(2):
            dp[n][i][j] = 1
    for i in range(n - 1, -1, -1):
        for j in range(2):
            dp[i][j][0] = (dp[i + 1][0][0] + 2 * dp[i + 1][1][0]) % mod
            if s[i] == '0':
                dp[i][j][1] = dp[i + 1][0][1]
            else:
                dp[i][j][1] = (dp[i + 1][0][0] + 2 * dp[i + 1][1][1]) % mod

    ans = dp[0][0][1]
    print(ans % mod)


if __name__ == "__main__":
    main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值