xtu寒假做题1月5日题解

文章讨论了一道递推题目,重点在于如何通过递推公式f(n)=3*f(n-2)+2*Σ(i>2且i是偶数)f(n-i)来求解。提出了使用前缀和优化方法,避免在大数值n时使用双重循环,提高效率。给出了C语言的代码实现作为示例。
摘要由CSDN通过智能技术生成

oj 1161

提示:递推

比较经典的一道题,要是对递推比较敏感,那么可以一眼判断这是个递推题,很明显的一个特征就是答案只跟 n n n 有关,并且有继承性(转移性)。

考虑一个经典的模型,如果我们用 f[n] 表示长度为 n n n 时的答案,那么如何建立递推关系:

既然考虑递推关系,那么就显然我们需要考虑递推的意义,比如,假设:f[n-2]f[n] 有贡献,那么这个贡献产生的意义是什么?

我们画个图:

首先我们定义下标:

在这里插入图片描述

然后我们考虑转移:

在这里插入图片描述

显然这就是意义,就是说,转移的意义就是:下标 n − 1 , n n-1, n n1,n,应该怎么摆法。更加抽象一点,我们将包含的下标 n n n 的块看成一个不可分割的整体,也就是说,最后一块不能被竖着从任何地方分开。那么我们需要考虑的就是,包含下标 n n n 的一个整块的摆法。

经过分析,实验我们可以得到,一个整块只能是偶数长度,并且摆法方式只有两种,长度为2时有三种:

在这里插入图片描述

长度为偶数时,只有两种:边框固定,中间只能横着摆(不信自己试试,除了这个摆法,其他的摆法一定可以从中分开)

在这里插入图片描述

那么我们得到的递推式子就是:
f ( n ) = 3 ∗ f ( n − 2 ) + 2 ∗ ∑ i > 2 并且 i 是偶数 f ( n − i ) f(n) = 3*f(n-2) + 2 * \sum _{i>2 并且 i是偶数} f(n-i) f(n)=3f(n2)+2i>2并且i是偶数f(ni)

#include <stdio.h>

typedef long long ll;

#define MOD 100003

int f[1003];

void init() {
    f[0] = 1;
    for (int i = 1; i <= 1000; ++i)
    {
        if (i >= 2) f[i] = f[i - 2];
        for (int j = i - 2; j >= 0; j -= 2)
            f[i] = (f[i] + f[j] * 2) % MOD;
    }
}

int main()
{
    init();
    int n;
    while (scanf("%d", &n) == 1 && n > 0)
    {
        printf("%d\n", f[n]);
    }
    return 0;
}

思考:如果 n 等 1 0 6 10^6 106 ,就不能用双重循环了,那么应该怎么做呢。

提示:前缀和,我们可以发现,实际上我们加的值就是与自己同奇偶性的长度的和。我们维护一个小于 n n n 的,奇数位置的和,偶数位置的和,然后在算答案时加起来即可。大家自己实现。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值