POJ1351 Number of Locks(数学)

截至写博客为止,貌似这是网上第一个采用数学公式来处理的。

 

网上的题解都是DFS或是动态规划,但感觉可以推公式直接用数学的方法处理,想了好久,终于推出公式。

 

题意:一个长度为n的由数字1,2,3,4 组成的序列,求至少有一对1,4相邻且2或3必须用上的方法数。

 

思路: 计A为有1,4相邻的方法数,B为有1,4相邻且无2,3的方法数,则答案为A - B

B很容易求,为2 ^ n - 2 ,再考虑A

 

计f(n)为有1,4相邻的方法数,g(n)为无1,4相邻但以1,或4开头的方法数

长度为n - 1且有1,4相邻的序列,后面接上1,2,3,4,仍然有1,4相邻,无1,4相邻但以1,4开头前面加上1,4 ,变成有1,4相邻的序列,故有递推公式

 

f[n] = 4 * f[n - 1 ]  + g[n - 1]

考虑g(n) ,1或4后面是2,3,方法数为2 * 2 *(4 ^(n - 2) - f(n - 2)),或者1或4后面数与他相同,则变成一个字问题,方法数为g(n - 1),故

 

g(n) =  2 * 2 *(4 ^(n - 2) - f(n - 2)) + g(n - 1)

 

故可采取递推方式

代码如下:

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include< string>
 6 #include<algorithm>
 7 #include<map>
 8 #include<queue>
 9 #include<vector>
10 #include<cmath>
11  using  namespace std;
12 typedef  long  long LL;
13  const  int N =  1008, INF =  0x3F3F3F3F;
14 LL f[N], g[N];
15  int main(){
16     f[ 1] =  0;
17     f[ 2] =  2;
18     g[ 1] =  2;
19     g[ 2] =  6;
20      for( int i =  3; i <=  17 ; i++){
21         f[i] =  4 * f[i -  1 ]  + g[i -  1];
22         g[i] = ( 1 <<( 2 * i -  2)) -  4 * f[i -  2] + g[i -  1];
23     }
24      int n;
25      while(~scanf( " %d ", &n) && n != - 1){
26         printf( " %d: %I64d\n ",n, f[n] - ( 1 << n) +  2);
27 
28     }
29 
30      return  0;

31 } 

 

 采用数学方法,代码如此简洁

转载于:https://www.cnblogs.com/IMGavin/p/5645097.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值