原题网址:
http://acm.hdu.edu.cn/showproblem.php?pid=1297
思路:
设当前n个学生时,排列为f ( n )。1:当第n个同学是男生是时,前边n-1个同学符合排列的情况f ( n-1 ) 都可以。2:若第n个同学是女生,那么第n-1个同学绝对得是女生。此种情况又分为两种情况:
1)前边n-2个人排序满足规则的,所以加上f (n-2)
2)就是以前的状态不符合情况,但是加上两个女生情况就可以了 。即 xxxxxxxxxxx男女 女女,所以还要加上f ( n-4 )
综上 f(n) = f(n-1) + f(n-2) + f(n-4)
#include <iostream>
#include <cstdio>
using namespace std;
#include <string.h>
#define N 10000
char dp[1010][N];
char temp[N];
// 大数a,b相加 ,结果放在c上
void f(char* a,char *b,char *c){
char s[N];
int i = strlen(a);
int j = strlen(b);
if(i<j){
int temp = i;
i = j;
j = temp;
}
int carry = 0;
int k;
for(k = 1;k <= i+1;k++){
int m;
if(j >= k)
m = a[i-k] + b[j-k] - 48 * 2 + carry;
else if( i >= k)
m = a[i-k] - 48 + carry;
else{
m = carry;
if(m == 0)break;
}
if(m >= 10){
carry = 1;
m-=10;
}
else{
carry = 0;
}
char c = m + 48;
s[k-1] = c;
}
k--;
k--;
for(int l = 0;l <= k;l++){
c[l] = s[k-l];
}
c[k+1] = '\0';
}
int main()
{
dp[0][0] = '1';
dp[1][0] = '1';
dp[2][0] = '2';
dp[3][0] = '4';
dp[0][1] = '\0';
dp[1][1] = '\0';
dp[2][1] = '\0';
dp[3][1] = '\0';
for(int i = 4;i <= 1000;i++){
f(dp[i-1],dp[i-2],temp);
f(temp,dp[i-4],dp[i]);
}
int n;
while(~scanf("%d",&n)){
printf("%s\n",dp[n]);
}
return 0;
}