鑰匙計數之一

鑰匙計數之一

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 1   Accepted Submission(s) : 1

Font: Times New Roman | Verdana | Georgia 

Font Size: ← →

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&lt;=16

Author

ecjtu_zhousc
 
分析

a[i]表示長度爲i的合法的鑰匙總數。
b[i]表示第i個槽爲1或4時合法的長度爲i的合法的鑰匙總數。
c[i]表示:不合法的長度爲i-1的鑰匙X + 最後一個新槽1/4(1或者4的槽),能夠構成合法的長度爲i的鑰匙時,不合法的長度爲i-1的鑰匙X的方案數

1、合法的長度爲i-1的鑰匙 + 任何1個新的槽,所構成的長度爲i的鑰匙一定是合法的,所以a[i]=a[i-1]*4

2、若不合法的長度爲i-1的鑰匙X + 最後一個新槽2/3(2或者3的槽),要構成合法的長度爲i的鑰匙,則X必定由1/4(1或者4的槽)的組合構成序列(原因在於後綴2或者3加上就成爲鑰匙的話,必然是沒滿足需要3個不同深度槽這一項,故X必然由1/4組成),但需要去除2種情況111....1111(全爲1),444....444(全爲4),所以
a[I]+=(2^(I-1)-2)*2(爲什麼是它,因爲前i-1個槽均可以是1或4,有這麼多種組合方式,減去上述兩種特殊情況,即這兩種特殊情況下,最後一個新槽爲2/3時仍不能構成合法的長度爲i的鑰匙。之所以乘2,是因爲最後一個新槽可以是2,也可以是3)。

3、若不合法的長度爲i-1的鑰匙X + 最後一個新槽1/4(1或者4的槽),要構成合法的長度爲i的鑰匙,設:x=Y(1/4) 即 長度爲i-1的鑰匙x=長度爲i-2的鑰匙y+第i-1個槽爲1/4(1或者4的槽)
則要在不合法的長度爲i-1的鑰匙X加上最後1個新槽1/4(1或者4的槽)成爲一個合法的長度爲i的鑰匙,
當且僅當第i-1位的槽是4/1時,加上第i位的1/4槽,才能滿足。
(因爲不合法的長度爲i-1的鑰匙X ,要麼就不滿足具有3個不同的槽,或不滿足至少有1對相連的槽其深度之差爲3,或同時不滿足。要在加上最後1個新槽1/4(1或者4的槽)後成爲長度爲i的合法的鑰匙,只可能是
A、前i-2位是1,2,3,4四種槽的任意組合+第i-1位的4+第i位的1
B、前i-2位是1,2,3,4四種槽的任意組合+第i-1位的1+第i位的4
C、在前兩種組合中去掉下面兩種情況--無法構成合法的長度爲i的鑰匙:
   前i-2位是1,4兩種槽的任意組合+第i-1位的4+第i位的1
   前i-2位是1,4兩種槽的任意組合+第i-1位的1+第i位的4
D、在前兩種組合中去掉下面這種情況:
   因爲在A情況下,“前i-2位是1,2,3,4四種槽的任意組合+第i-1位的4”包含了長度爲i-1的,第i-1位爲4的合法的長度爲i-1的鑰匙X
   在B的情況下“前i-2位是1,2,3,4四種槽的任意組合+第i-1位的1”包含了長度爲i-1的,第i-1位爲1的合法的長度爲i-1的鑰匙X
   但第3類的前提是“不合法的長度爲i-1的鑰匙X”,兩者矛盾。因此,要減去第i-1個槽爲1或4時合法的長度爲i-1的合法的鑰匙總數 即b[i-1]
 )
故第3類中,c[i]==(4^(i-2)-2^(i-2))* 2 - b[i-1];
  所以a[i]+=c[i]

4、修正b[i]
   b[i]表示第i個槽爲1或4時合法的長度爲i的合法的鑰匙總數。
   在求得a[i-1]後可知長度爲i-1的合法的鑰匙總數。每種方案中增加第i位的1/4槽(1或者4的槽),總是b[i]中數據的一部分。即2*a[i-1]
   在求得c[i]後可知長度爲i-1的不合法的鑰匙 + 第i位的1/4槽(1或者4的槽)所能構成的合法的長度爲i的第i位爲1/4槽的鑰匙總數,也是b[i]中數據的一部分。即c[i]
   故b[i]=2*a[i-1]+c[i]

 
 
 
 
 
 
  1. #include<stdio.h>  
  2.  
  3. #include<math.h>   
  4.   
  5. int main ()  
  6.   
  7. {  
  8.   
  9.     int        i;  
  10.   
  11.     __int64 c[32], a[32], b[32];    //b[i]記錄以1 4結尾的數   
  12.   
  13.     a[2] = 0;  
  14.   
  15.     a[3] = 8;  
  16.   
  17.     b[2] = 0;  
  18.   
  19.     b[3] = 4;  
  20.   
  21.     printf ("N=2: 0\nN=3: 8\n");  
  22.   
  23.     for (i = 4; i <= 31; i++)  
  24.   
  25.     {  
  26.   
  27.         a[i] = a[i - 1] * 4;  
  28.   
  29.         a[i] += (__int64) pow (2,i) - 4;    //以2 3 結尾的   
  30.   
  31.         c[i] = ((__int64) pow (4,i-2) - (__int64) pow (2, i - 2)) * 2 - b[i - 1];  
  32.   
  33.         a[i] += c[i];  
  34.   
  35.         b[i] = a[i - 1] * 2 + c[i];  
  36.   
  37.         printf ("N=%d: %I64d\n", i, a[i]);  
  38.   
  39.     }  
  40.   
  41.     return 0;    
  42.   
  43. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章