• 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, f[n] - (1 << n) + 2);
    27 
    28     }
    29 
    30     return 0;

    31 } 

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

  • 相关阅读:
    mybatis-spring 集成
    maven 插件深入了解
    maven 常用插件3
    maven 插件2
    <转载> maven 详解 http://www.cnblogs.com/binyue/p/4729134.html
    linux base shell 基础语法
    浏览器运行原理
    <转载> js 闭包
    dubbo 学习资料
    HTTP
  • 原文地址:https://www.cnblogs.com/IMGavin/p/5645097.html
Copyright © 2020-2023  润新知