鑰匙計數之一(hdu-1438)

鑰匙計數之一

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2113    Accepted Submission(s): 1006


Problem Description

一把鎖匙有N個槽,槽深爲1,2,3,4。每鎖匙至少有3個不同的深度且至少有1對相連的槽其深度之差爲3。求這樣的鎖匙的總數。

 Input

本題無輸入

 Output

對N>=2且N<=31,輸出滿足要求的鎖匙的總數。

 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

解析:

一個遞推的重排列問題

a[i]來表示長度爲i的槽是鑰匙的情況

若a[i-1]合法,則第i個可以是1,2,3,4 =>  a[i]=a[i-1]*4;

若a[i-1]不合法,有兩種情況:

1.n-1個裏有相鄰相差3的槽,且不合法,n-1個只能是1,4全排列,要要去掉全爲1或者全爲4的情況

2.n-1個裏沒有相鄰相差3的槽,我們用b[n]來表示這種情況且合法的

呢麼要讓n個合法,n-1一定是1或者4,n-2個可以是任意情況:4^(n-2),有(1,4),(4,1)兩種情況

2*(4^(n-2)),這2*(4^(n-2))個裏要減去n-2個裏全爲1或者4的情況: 2^(n-2),還要減去n-1裏n-1位是(1或者4)

且本身就合法的情況b[n-1],

ac:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

int main()
{
    int i;
    ll temp,a[32],b[32];//b[i]記錄以1 4結尾的數
    a[2]=0;
    a[3]=8;
    b[2]=0;
    b[3]=4;
    printf("N=2: 0\nN=3: 8\n");
    for(i=4;i<=31;i++)
    {
        a[i]=a[i-1]*4;//n-1已經合法
        a[i]+=(ll)(2*(pow(2,i-1)-2));//n-1序列全爲1,4
        temp=((ll)pow(4,i-2)-(ll)pow(2,i-2))*2-b[i-1];//結尾爲(1,4)且合法
        a[i]+=temp;
        b[i]=a[i-1]*2+temp;//n個序列,結尾爲1,4且合法,加上n-1個序列且合法的一半(1或者4)
        printf("N=%d: %I64d\n",i,a[i]);
    }
    return 0;
}

 

 

 

ac:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章