51nod 1043 幸运号码【dp+滚动数组】

本文介绍了一种通过动态规划算法解决寻找特定长度的幸运号码数量的问题。幸运号码是指一个长度为2N的数,其中左边N个数的和等于右边N个数的和。文章详细阐述了动态规划的状态定义、状态转移方程,并提供了去除前导0情况的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基准时间限制:1 秒 空间限制:131072 KB 分值: 20  难度:3级算法题
1个长度为2N的数,如果左边N个数的和 = 右边N个数的和,那么就是一个幸运号码。
例如:99、1230、123312是幸运号码。
给出一个N,求长度为2N的幸运号码的数量。由于数量很大,输出数量 Mod 10^9 + 7的结果即可。
Input
输入N(1<= N <= 1000)
Output
输出幸运号码的数量 Mod 10^9 + 7
Input示例
1
Output示例
9

思路:


1、计数问题,考虑dp:

①我们肯定是根据数位进行dp,那么设定dp【i】【j】表示现在一个数,一共长度为i,和为j的方案数。

②那么不难推出其状态转移方程:
dp【i】【j】=dp【i】【j】+dp【i-1】【j-k】,其中k表示当前第i位最后一个数字为k。

③对于状态转移过程中,注意去掉前导0的情况发生。



2、那么我们答案就是Σdp【n】【i】*dp【n】【i】?

很显然不是,因为我们要得到的是长度为2n的一个数,而非两个不含前导0的部分连接在一起,我们只要保证前边n个数所组成的方案中,不包含前导0即可,后半部分是可以有前导0存在的,所以我们再设定一个dp2【i】【j】,状态转移方程一样,只是这个部分我们不对前导0进行处理。

那么答案就是:Σdp【n】【i】*dp2【n】【i】(1<=i<=n*9);


3、因为我们设定的数组偏大,而又考虑到第i位只和第i-1位方案数有关,那么我们考虑用滚动数组进行空间优化。

另外,因为思路比较挫,暴力姿势如果不太好的话会TLE掉、注意暴力姿势。


4、其实这个题打表也是个很好的选择,暴力Dp反正也不会多久,跑个表直接打印粗来。。。。(继续膜效率榜第一的方法.................)


Ac代码:

#include<stdio.h>
#include<string.h>
using namespace std;
#define mod 1000000007
#define ll __int64
ll dp[2][9050];
ll dp2[2][9050];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(dp,0,sizeof(dp));
        memset(dp2,0,sizeof(dp2));
        dp[0][0]=1;
        dp2[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=i*9;j++)
            {
                for(int k=0;k<=9;k++)
                {
                    int q=j-k;
                    if(q>=0)
                    dp2[1][j]=(dp2[1][j]+dp2[0][q])%mod;
                    if(i==1&&k==0)continue;
                    if(q>=0)
                    dp[1][j]=(dp[1][j]+dp[0][q])%mod;
                }
            }
            for(int j=0;j<=i*9;j++)
            {
                dp[0][j]=dp[1][j],dp2[0][j]=dp2[1][j];
                dp[1][j]=0,dp2[1][j]=0;
            }
        }
        ll output=0;
        for(int i=1;i<=n*9;i++)
        {
            output=(output+(dp[0][i]*dp2[0][i])%mod)%mod;
        }
        printf("%I64d\n",(output+mod)%mod);
    }
}






内容概要:本文介绍了多种开发者工具及其对开发效率的提升作用。首先,介绍了两款集成开发环境(IDE):IntelliJ IDEA 以其智能代码补全、强大的调试工具和项目管理功能适用于Java开发者;VS Code 则凭借轻量级和多种编程语言的插件支持成为前端开发者的常用工具。其次,提到了基于 GPT-4 的智能代码生成工具 Cursor,它通过对话式编程显著提高了开发效率。接着,阐述了版本控制系统 Git 的重要性,包括记录代码修改、分支管理和协作功能。然后,介绍了 Postman 作为 API 全生命周期管理工具,可创建、测试和文档化 API,缩短前后端联调时间。再者,提到 SonarQube 这款代码质量管理工具,能自动扫描代码并检测潜在的质量问题。还介绍了 Docker 容器化工具,通过定义应用的运行环境和依赖,确保环境一致性。最后,提及了线上诊断工具 Arthas 和性能调优工具 JProfiler,分别用于生产环境排障和性能优化。 适合人群:所有希望提高开发效率的程序员,尤其是有一定开发经验的软件工程师和技术团队。 使用场景及目标:①选择合适的 IDE 提升编码速度和代码质量;②利用 AI 编程助手加快开发进程;③通过 Git 实现高效的版本控制和团队协作;④使用 Postman 管理 API 的全生命周期;⑤借助 SonarQube 提高代码质量;⑥采用 Docker 实现环境一致性;⑦运用 Arthas 和 JProfiler 进行线上诊断和性能调优。 阅读建议:根据个人或团队的需求选择适合的工具,深入理解每种工具的功能特点,并在实际开发中不断实践和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值