【题意概述】
有n个位置,每个位置可以放F或者M,规定一种合法的放置方案为不存在单独的F(即每个F的左边或者右边必须至少有一个F),问有多少种放置方案。
【题解】
假设有一种合法的放置方案,有n-1个位置,那么我们在末尾多放一个M,必定是一个合法的方案。(放F则不一定)
有n-2个位置的合法放置方案,我们在末尾多放FF,必定是一个合法的方案。(其实放MM也是必定合法的,但是会和上一种情况重复,不能考虑进去。FM和MF则不能保证合法)
有n-2个位置的不合法放置方案,如果能够通过放置两个位置变成合法的,那么它一定以MF结尾,我们可以放置FF或者FM。也就是在n-4个位置的合法方案后面放置MFFM或者MFFF,但是MFFM会与第一种情况重复,所以我们只计算MFFF的。
那么我们就可以得出递推式:f[i]=f[i-1]+f[i-2]+f[i-4],(i≥4).
题目没有取模,所以我们要写成大数加法。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define LL long long 5 #define N 1001 6 #define rg register 7 using namespace std; 8 int n,f[N][N]; 9 inline int read(){ 10 int k=0,f=1; char c=getchar(); 11 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 12 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 13 return k*f; 14 } 15 inline void Pre(){ 16 for(rg int i=1;i<=4;i++) f[i][0]=1; 17 f[1][1]=1; f[2][1]=2; f[3][1]=4; f[4][1]=7; 18 } 19 inline void add(int x,int y){ 20 int len=max(f[x][0],f[y][0]); 21 for(rg int i=1;i<=len;i++) f[x][i]+=f[y][i]; 22 for(rg int i=1;i<=len;i++)if(f[x][i]>9){ 23 int tmp=f[x][i]/10; 24 f[x][i]%=10; 25 f[x][i+1]+=tmp; 26 } 27 while(f[x][len+1]>0) len++; 28 f[x][0]=len; 29 } 30 inline void Work(){ 31 for(rg int i=5;i<=N;i++){ 32 add(i,i-4); 33 add(i,i-2); 34 add(i,i-1); 35 } 36 } 37 int main(){ 38 Pre(); 39 Work(); 40 while(scanf("%d",&n)!=EOF){ 41 int len=f[n][0]; 42 for(rg int i=len;i;i--) printf("%d",f[n][i]); 43 puts(""); 44 } 45 return 0; 46 }