题目:
题解:
dp[i][j] 表示长度为i,1的个数不多于j的方案数
转移就是
dp[i][j]=dp[i−1][j−1]+dp[i−1][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");
}
本文介绍了一种使用动态规划方法解决特定二进制序列生成问题的技术。通过定义状态dp[i][j]来表示长度为i且1的个数不超过j的二进制序列数量,文章详细阐述了状态转移方程及其应用,并提供了完整的C++实现代码。

被折叠的 条评论
为什么被折叠?



