您的位置:首页 > 编程语言 > PHP开发

hdu 1480 钥匙计数之二

2011-09-23 13:20 190 查看
 

一、题目

Problem Description
一把钥匙有N个槽,2<N<26槽深为1,2,3,4,5,6。每钥匙至少有3个不同的深度且相连的槽其深度之差不得为5。求这样的钥匙的总数。

Input

本题无输入
Output

对2<N<26,输出满足要求的钥匙的总数。
Sample Output

N=3: 104
N=4: 904
N=5: 5880
.
.
.
N=25: 8310566473196300280

 

二、题目分析

提交完本题后,颇觉有递推的味道。

出发点:构造结果ans
=num[1]+……+num[6];其中num[i]表示以i为最后一个槽的高度;计算出num[i],从而得出结果。

 

首先进行初始化分析,即n=3时。

“相连的槽其深度之差不得为5”——1,6这两个高度不能相邻;而2,3,4,5这四个高度等价,且之后n=4,5,……25的计算过程中均有此规律。即num[1]=num[6],num[2]=num[3]=num[4]=num[5],在写代码时注意到这点便可以不需要用到数组;

num[1]=num[6]=16;num[2,3,4,5]=18;

ans[3]=104;

 

(下面是重点)

再由n-1递推分析n的情况:

1、当前面n-1个排列是钥匙的排列,则

A、对2,3,4,5作为第n个高度来说都能满足题意,有num[2,3,4,5]=ans[n-1];

B、对1,6(1,6等价,记号不同而已)来说,第n-1个高度不能为6,1,即要去掉

几个不符合题意的组合;num[1]=ans[n-1]-num__[6](前n-1个中最后一个为6的个数,实际写代码时要用另一个数组保存)。同理 num[6]=ans[n-1]-num__[1](……)。也即num[1,6]=ans[n-1]-num__[6](……);

 

2、当前面n-1个排列不是钥匙的排列,则

A、对i(i=2,3,4,5)作为第n个高度来说能满足钥匙的要求,则说明前面n-1个排列里仅有两类高度,且与i不同,加上i就刚
4000
好3类高度满足题意。那么前面两类高度的选法总数是从其余5类高度里选出两类,即C(5,2),但1,6不能同时选,故组合数为

C(5,2)-1。 再看排列数,n-1个位置,每个位置可任选两类,但不能全部是同一类高度,故排列数2^(n-1)-2。

B、对i=1,6,同上面分析。因为1,6等价,所以我这里举i=1来说,前面两类高度里我有两种取法,选6和不选6。

对于选6,组合数是C(4,1)(剩下2,3,4,5任意选一);再看排列数,每个位置可任选两类,但不能全部是同一高度,且最后一个也即第n-1个位置处不能为6,也可换个说法,最后一个位置放i(i=2,3,4,5),前面n-2个位置任选6和i放,排列数4×(2^(n-2)-1)。前面不能全是和后面n-1的位置同一高度

对于不选6,组合数是C(4,2);再看排列数,每个位置可任选两类,且不能全部是同一类高度,排列数2^(n-1)-2。

 

把上面的组合数与排列数相乘便得到一种情况下的num[i]的值,所有情况的值相加便得到结果。

 

三,源代码

 

#include <stdio.h>
#include <math.h>

int main()
{
__int64 num[3],ans[26],t=16;
int i;
ans[3]=104;
for(i=4;i<=25;i++)
{
num[1]=ans[i-1];
num[2]=ans[i-1]-t;
num[1]+=9*((__int64)pow(2,i-1)-2);
num[2]+=4*((__int64)pow(2,i-2)-1)+6*((__int64)pow(2,i-1)-2);
ans[i]=4*num[1]+2*num[2];
t=num[2];
}
for(i=3;i<=25;i++)
{
printf("N=%d: %I64d\n",i,ans[i]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  output n2 input c