分析过程(1)
设:F(n)表示n个人的合法队列,则:
按照最后一个人的性别分析,他要么是男
,要么是女,所以可以分两大类讨论:
1、如果n个人的合法队列的最后一个人是男,
则对前面n-1个人的队列没有任何限制,他只要站在最后即可,
所以,这种情况一共有F(n-1);
分析过程(2)
2、如果n个人的合法队列的最后一个人是女,
则要求队列的第n-1个人务必也是女生,这就是说
,限定了最后两个人必须都是女生,这又可以分两种情况:
分析过程(3)
2.1、如果队列的前n-2个人是合法的队列,则显然后面再
加两个女生,也一定是合法的,这种情况有F(n-2);
分析过程(4)
2.2、但是,难点在于,即使前面n-2个人不是合法的队列
,加上两个女生也有可能是合法的,当然,这种长度为n-2的
不合法队列,不合法的地方必须是尾巴,就是说,这里说的长
度是n-2的不合法串的形式必须是“F(n-4)+男+女”,这种情况一共有F(n-4).
所以,通过以上的分析,可以得到递推的通项公式:
F(n)=F(n-1)+F(n-2)+F(n-4)
(n>3)
然后就是对n<=3 的一些特殊情况的处理了,显然:
F(0)=1
(没有人也是合法的,这个可以特殊处理,就像0的阶乘定义为1一样)
F(1)=1
F(2)=2
F(3)=4
但是这个题还有一个难点,就是结果会超出现有所有整型变量的范围,所以要用大整数加法来做,
下面附带我的代码:(写的有点儿乱啊)
#include<stdio.h>
#include<string.h>
void add(char str[],char a[],char b[])
{
int m,n,i,num1[250],num2[250],sum[250];
memset(num1,0,sizeof(num1));
memset(num2,0,sizeof(num2));
memset(sum,0,sizeof(sum));
strrev(a);strrev(b);
for(i=0;a[i];i++)
num1[i]=a[i]-'0';
m=i-1;
for(i=0;b[i];i++)
num2[i]=b[i]-'0';
n=i-1;
if(m<n)m=n;
for(i=0;i<=m;i++)
{
sum[i]=num1[i]+num2[i]+sum[i];
if(sum[i]>=10)
{
sum[i]=sum[i]-10;
sum[i+1]++;
}
}
if(sum[m+1]==1)m++;
for(i=0;i<=m;i++)
str[i]=sum[i]+'0';
str[i]='\0';
strrev(str);
}
int main()
{
int n,i;
char
str[1005][400],c[400],b[400],a[400],d[400];
strcpy(str[1],"1");
strcpy(str[2],"2");
strcpy(str[3],"4");
strcpy(str[4],"7");
for(i=5;i<=1001;i++)
{
strcpy(a,str[i-1]);
strcpy(b,str[i-2]);
strcpy(c,str[i-4]);
add(d,a,b);
add(str[i],d,c);
a[0]=b[0]=c[0]=d[0]='\0';
}
while(scanf("%d",&n)!=EOF)
puts(str[n]);
return 0;
}