算法竞赛宝典-递推算法

这篇博客是关于算法竞赛中递推算法的应用,包括多种递推问题的解析和解题思路,如偶数3的个数、布阵问题、极值问题、区域划分等。每道题目都提供了详细的时间限制、内存限制和解题思路。
摘要由CSDN通过智能技术生成

算法竞赛宝典-递推算法

Problem A
【递推】挖地雷 待更新

问题 B: 【递推】偶数3的个数

时间限制: 1 Sec 内存限制: 64 MB
题目描述
“报告,我军已探出地雷阵中所有的地雷位置,并且还发现了一份使用说明书。”一个黑暗军团的小兵匆忙跑来,交给修罗王一张纸。

只见这张纸上面写道:“我是一颗萌萌的地雷,拆除我很容易,看到我身上标着的整数N了吗?你只要输入这个N位数中有多少个数中有偶数个数字3就可以把我拆除哦,加油!你行的。”

输入
一个整数N。

输出
输出这个N位数中有多少个数中有偶数个数字3。

样例输入
2
样例输出
73

思路
对每一位数字而言,有两种选择:3或非3,非3的选择有9种方案(特别地,最高位只有8种)
因此使用数组存储i位数时 奇数个3与偶数个3的数量,转移一下即可
转移方法:偶数=偶数并且新一位不是3+奇数并且新一位是3
奇数=奇数并且新一位不是3+偶数并且新一位是3

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+5;
const int mod=10000;
int a[N],b[N];
int main()
{
   
    int n;
    scanf("%d",&n);
    if(n==1)
    {
   
        printf("9");
        return 0;
    }
    a[1]=8;
    b[1]=1;
    for(int i=2;i<=n;i++)
    {
   
        a[i]=a[i-1]*9+b[i-1];
        b[i]=a[i-1]+b[i-1]*9;
    }
    printf("%d",a[n]);
    return 0;
}
问题 C: 【递推】布阵

时间限制: 1 Sec 内存限制: 64 MB
题目描述
黑暗军团在城外的草地上布阵,如果把草地划分成很多大小一样的方格,看成无限大的棋盘,军团从中心点出发,每次只能向上或向左或向右移动一步(移动的过程中,走过的格子不能再次进入)。就能到达相邻的一个格子里,如果一共移动了N步,总共有多少种走法呢?

输入
一个整数即N,N≤30。

输出
输出步数。

样例输入
2
样例输出
7

思路:
移动共有上,左,右三种,我将其划分为上移(向上)和平移(左/右)两大类。
由于我们不能移动回已经走过的位置,平移操作方向一旦确定,便只可能向一个方向移动。也就是说,进行过平移操作的状态的下一步如果选择平移操作,方向是唯一确定的,而当上一步操作进行的是上移操作的时候,平移可以从左右两个方向当中选择一个。
而上移操作不受上述条件限制,任何一个状态皆可进行上移操作。
下面的代码中,数组a存储平移,数组b存储上移。
初始状态:2种平移1种上移。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e2+5;
const int mod=10000;
ll a[N],b[N];
int main()
{
   
    int n;
    scanf("%d",&n);
    a[1]=2;
    b[1]=1;
    for(int i=2;i<=n;i++)
    {
   
        a[i]=a[i-1]+b[i-1]*2;
        b[i]=a[i-1]+b[i-1];
    }
    printf("%lld",a[n]+b[n]);
    return 0;
}
问题 D: 【递推】极值问题

时间限制: 1 Sec 内存限制: 64 MB
题目描述
修罗王:“等了这么久,怎么攻城的魔法炮还没有响?”

邪狼满头大汗:“这魔法炮使用起来太复杂了,每次操作都需要输入验证码,首先它会产生一个正整数k,你要根据这个数输入正确的m和n两个整数才能发射。”

修罗王:“这是谁设计的炮啊,不考虑客户体验,界面友好性吗?让我来看看…”

现已知m,n为整数,且满足下列两个条件:

(1)m、n属于{1,2,…,k},即1≤m,n≤k

(2)(n2-mn-m22=1

你的任务是:根据输入的正整数k(1≤k≤109),求一组满足上述两个条件的m、n,并且使m2+n2的值最大。例如从键盘输入k=1995,则输出m=987 ,n=1597。

样例输入
1995
样例输出
987 1597

思路
用n=m+k代入条件2,将表达式化简可以化简成(k2+mk-m2)2=1,平方内所有项取负号可得到与条件2相同的式子,因此符合条件的数列即为斐波那契数列,只需找到斐波那契数列当中最大的比n小的连续两项即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e2+5;
const int mod=10000;
int main()
{
   
    int n,a=1,b=1;
    scanf("%d",&n);
    while(a+b<=n)
    {
   
        int tmp=b;
        b=a+b;
        a=tmp;
    }
    printf("%d %d",a,b);
    return 0;
}
问题 E: 【递推】区域划分问题

时间限制: 1 Sec 内存限制: 64 MB
题目描述
已知黑暗军团的魔法炮发射轨迹成直线,现有n座魔法炮产生n(n≤500)条直线将地面(可视为平面,因为魔法炮具有降维属性,即可将三维空间降为二维空间)分割成了许多区域,并且已有p(p≥2)条直线相交于同一点,问n条直线最多能将平面分割成多少个不同的区域?

输入
输入一个数n和p。

输出
输出分割的区域数。

样例输入
3 2
样例输出
7
思路
先考虑交于同一点的p条直线,共将平面分成p*2个区域,然后往这个平面增加n-p条直线。每一条直线可以被当前k条直线截成k+1段,就多分成k+1个区域。递推即可得到结果。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e2+5;
const int mod=
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值