HDU:1279  Children’s Queue 终于…

本文探讨了一种特定条件下的队列排列问题,利用递推公式F(n)=F(n-1)+F(n-2)+F(n-4)解决,并通过自编的大整数加法实现算法,有效解决了结果超出常规整型变量范围的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分析过程(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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值