钥匙计数之一(HDU-1483)

Problem Description

一把锁匙有N个槽,槽深为1,2,3,4。每锁匙至少有3个不同的深度且至少有1对相连的槽其深度之差为3。求这样的锁匙的总数。

Input 

本题无输入

Output

对N>=2且N<=31,输出满足要求的锁匙的总数。

Sample Input

无 

Sample Output

N=2: 0
N=3: 8
N=4: 64
N=5: 360
..
..
..
..
..
..
..

N=31: ...

注:根据Pku Judge Online 1351 Number of Locks或 Xi'an 2002 改编,在那里N<=16

思路:一个递推的重排列问题,状压DP也能做,但还是果断偷懒用递推了。。。

用 a[i] 来存储为 i 个槽时的钥匙数,假设一个钥匙有 n 个槽

若该钥匙的前 n-1 个槽合法,则第 n 个槽的深度可为任意深,此时有 a[n]=4*a[n-1]

若该钥匙的前 n-1 个槽不合法,有以下两种情况:

1)前 n-1 个有相邻且相差深度为3的槽,但只有两种深度,此时由于有相邻且相差深度3的槽,因此只能为1、4深度的全排列,再减去只有深度为 1、4 的情况,即有 a[n]=2*(2^(n-1)-2)

2)前 n-1 个没有相邻且相差深度3的槽,由于相差深度为3的槽只有1、4,因此如果想要让其合法,只有最后一个排列是1或4时才可,因此当第 n 个确定时,第 n-1 个槽也就确定了

用 b[n-1] 来表示一个 n-1 的排列中符合该种情况且合法的状态数,即用 b[n-1] 表示最后一个数是1或4,去掉后这些排列中无相邻且相差深度为3的槽

由于最后两个 n、n-1 均可确定,因此前 n-2 个槽可为任意深度,即有 4^(n-2) 个,再减去只有深度为 1、4 的情况,即减去 2^(n-2) 个

此时,每种情况均可确定,但由于最后 n 位置的槽可能为 1 或 4,因此要乘以 2,再减去前 n-1 项合法的答案即 b[n-1]

即有:a[n]=(2*( 4^(n-2)-2^(n-2) ) )*2-b[n-1]

Source Program

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<ctime>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 32
#define MOD 10007
#define E 1e-6
#define LL long long
using namespace std;
LL a[N],b[N];
int main()
{
    a[2]=0;
    a[3]=8;
    b[2]=0;
    b[3]=4;
	for(int i=2;i<=31;i++){
        for(int j=4;j<=i;j++){
            a[i]=4*a[i-1];
            a[i]+=2*(LL)(pow(2,i-1)-2);
            a[i]+=2*(LL)(pow(4,i-2)-(LL)pow(2,i-2))-b[i-1];
            b[i]=2*a[i-1]+2*(LL)(pow(4,i-2)-(LL)pow(2,i-2))-b[i-1];
        }
        cout<<"N="<<i<<": "<<a[i]<<endl;
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值