[luogu2727][USACO3.2]Stringsobits(dp)

本文介绍了一种使用动态规划方法解决特定二进制序列生成问题的技术。通过定义状态dp[i][j]来表示长度为i且1的个数不超过j的二进制序列数量,文章详细阐述了状态转移方程及其应用,并提供了完整的C++实现代码。

题目:

我是超链接

题解:

dp[i][j] 表示长度为i,1的个数不多于j的方案数
转移就是 dp[i][j]=dp[i1][j1]+dp[i1][j] 前一项表示这一位填1,后一项为这一位填0
注意这不是组合数公式啊
因为转移的时候要分成两部分j<=i和j>i,不能因为j大于i就是1,应当是dp[i][i] (因为状态设计的是“不多于j”嘛)
预处理完了之后,对于这一位来说,dp[i][L]=dp[i-1][L]+dp[i-1][L-1] 倒序循环i
如果I比dp[i-1][L]大,说明这一位是1(因为0都轮完了还没到I,只能轮1,说明我们要求的这个数字包含在1的情况里。(因为之前的都小于I)。那么我们就可以把I扣除掉bit[k]=0的情况)

代码:

#include <cstdio>
using namespace std;
long long ii;int n,l,i,j,d[50][50];
int main()
{
    scanf("%d%d%lld",&n,&l,&ii);
    for (i=0;i<=n;i++) d[i][0]=1,d[0][i]=1;
    for (i=1;i<=n;i++)
      for (j=1;j<=n;j++)
        if (j<=i)
          d[i][j]=d[i-1][j]+d[i-1][j-1];
        else d[i][j]=d[i][i];
    for (i=n;i>=1;i--)
      if (ii>d[i-1][l])
      {
        printf("1");
        ii-=d[i-1][l]; l--;
      }else printf("0");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值