//dp
#include <cstring>
#include <cstdio>
#include <vector>
#include <iostream>
#include <cmath>
#include <vector>
#include <utility>
using namespace std;
typedef long long ll;
const int maxn=35;
//dp[i][0]是i个,结尾是L,dp[i][1]代表结尾是1个U,dp[i][2]代表结尾两个U,j>=3代表非法,不计算 dp代表答案有多少种
//dp计算不含有U长度>=3的情况数量,没有连续3个的U,那么U最多两个相连,所以按照结尾连续的U的数量进行分类
int dp[maxn][3],n,ans[maxn];
int main(void){
dp[1][0]=1;
dp[1][1]=1;
for(int i=2;i<=30;++i){
dp[i][0]=dp[i-1][0]+dp[i-1][1]+dp[i-1][2];
dp[i][1]=dp[i-1][0];
dp[i][2]=dp[i-1][1];
}
//用总情况的数量减去不包括U长度>=3的数量
for(int i=1;i<=30;++i) ans[i]=(1<<i)-dp[i][0]-dp[i][1]-dp[i][2];
while(scanf("%d",&n)==1 && n){
printf("%d\n",ans[n]);
}
return 0;
}
设答案为f(n),长度为n,至少有三个连续的U的情况数量,就是一个函数,那么如何求这个函数呢? 设 i , i + 1 , i + 2 , 1 < = i < = n − 2 i,i+1,i+2,1<=i<=n-2 i,i+1,i+2,1<=i<=n−2是最靠左边的连续三个U,所以对于1-i-1这一段,是没有三个连续的U的,所以i-2肯定是L,如果i-2是U,那么i,i+1,i+2就不是最靠左的了。所以1-i-2是没有三个连续的U,那么就是 g ( i − 2 ) = 2 i − 2 − f ( i − 2 ) g(i-2)=2^{i-2}-f(i-2) g(i−2)=2i−2−f(i−2)这么多种,右边是 2 n − i − 2 2^{n-i-2} 2n−i−2种,f(0)=f(1)=f(2)=0,f(3)=1,g(0)=1,当i=1时,没有i-1位存在,i-2=-1,一共有 2 n − 3 2^{n-3} 2n−3种,所以 f ( n ) = 2 n − 3 f(n)=2^{n-3} f(n)=2n−3,所以长度为n时, 1 < = i < = n − 2 1<=i<=n-2 1<=i<=n−2,依次相加得到 f ( n ) = 2 n − 3 + ∑ i = 2 n − 2 g ( i − 2 ) ∗ 2 n − i − 2 f(n)=2^{n-3}+\sum_{i=2}^{n-2}g(i-2)*2^{n-i-2} f(n)=2n−3+∑i=2n−2g(i−2)∗2n−i−2
#include <cstring>
#include <cstdio>
#include <vector>
#include <iostream>
#include <cmath>
#include <vector>
#include <utility>
using namespace std;
typedef long long ll;
const int maxn=35;
int f[maxn],g[maxn],n;
int main(void){
f[3]=1;
g[0]=1;
g[1]=2;
for(int i=4;i<=30;++i){
f[i]=2*f[i-1]+g[i-4]; //f[n]=2*f[n-1]+g[n-4]
g[i-2]=(1<<(i-2))-f[i-2];
}
while(scanf("%d",&n)==1 && n){
printf("%d\n",f[n]);
}
return 0;
}