//f[i] i个box 放U和L 至少连续3U的方法数
ll g[N+20];//g[i] i个box 放U和L 没有连续3U的方法数 g[i]=2^n-f[i]
// 根据第一次出现的连续3U进行分类计数 若i~i+2为3U则i-1只能为L 前面i-2个不能有3U方法为g[i-2] 后面n-i-2个box任意 2^(n-i-2)
// f[i]=segam(g[i-2]2^(n-i-2) i=2~n-2 ) +2^(n-3)(i==1时)
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=35;
const int mod=10056;
typedef long long ll;
ll f[N+20];//f[i] i个box 放U和L 至少连续3U的方法数
ll g[N+20];//g[i] i个box 放U和L 没有连续3U的方法数 g[i]=2^n-f[i]
// 根据第一次出现的连续3U进行分类计数 若i~i+2为3U则i-1只能为L 前面i-2个不能有3U方法为g[i-2] 后面n-i-2个box任意 2^(n-i-2)
// f[i]=segam(g[i-2]2^(n-i-2) i=2~n-2 ) +2^(n-3)(i==1时)
void init()
{
f[1]=f[2]=0;
g[0]=1;//
g[1]=2;
g[2]=4;
for(int i=3;i<=N;i++)
{
f[i]=1<<(i-3);//3U第一次k=1出现
for(int k=2;k<=i-2;k++)
{
f[i]+=g[k-2]*(1<<(i-k-2));
}
g[i]=(1<<i)-f[i];
}
}
int main()
{
int n;
init();
while(cin>>n&&n)
{
cout<<f[n]<<endl;
}
return 0;
}

本文介绍了一种使用动态规划方法解决计数问题的算法,具体为计算在一个由U和L组成的长度为n的序列中,至少包含一次连续三个U的可能排列数量。通过递推公式计算不含连续三个U的排列数,进而得出目标排列的数量。

525

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



