钥匙计数之一

来源:互联网 发布:淘宝内部券微信公众号 编辑:程序博客网 时间:2024/04/29 17:29

钥匙计数之一

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: 0N=3: 8N=4: 64N=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]

 
 
 
 
 
 
[csharp] view plaincopyprint?
  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. }  
0 0
原创粉丝点击