zoukankan      html  css  js  c++  java
  • 洛谷 P1573 栈的操作

    题目描述

    现在有四个栈,其中前三个为空,第四个栈从栈顶到栈底分别为1,2,3,…,n。每一个栈只支持一种操作:弹出并压入。它指的是把其中一个栈A的栈顶元素x弹出,并马上压入任意一个栈B中。但是这样的操作必须符合一定的规则才能进行。规则1:A栈不能为空。规则2:B栈为空或x比B栈栈顶要小。

    对于给定的n,请你求出把第四个栈的n个元素全部移到第一个栈的最少操作次数。

    由于最少操作次数可能很多,请你把答案对1000007取模。

    输入输出格式

    输入格式:
    一行,一个n

    输出格式:
    一行,一个正整数,为把最少操作次数 mod 1000007的值

    输入输出样例

    输入样例#1:
    2
    输出样例#1:
    3
    说明

    对于30%的数据,n<=8

    对于60%的数据,n<=60

    对于100%的数据,n<=2*10^9

    此题实质上是Hanoi四塔问题。

    那么Hanoi四塔问题是不是可以通过三塔问题的结论来解决呢?答案是:可以,首先要知道,三塔问题是借助1个中间柱完成转移,四塔问题是借助2个中间柱完成转移,以上两句话看似是废话,其实很重要!

    四塔问题可以转化为:对于N个盘子的四塔问题,先将j(0<=j<=N)个盘子通过两个中间柱(一个中间柱,一个目标柱)移动到另一个目标柱,然后将N-j个盘子通过一个中间柱移动到目标柱,最后将j个盘子通过两个中间柱(一个起始柱,一个中间柱)转移到目标柱

    递推方程:H[i]表示三塔问题的结论,即i个盘子通过一个中间柱转移需要多少步。F[i]表示四塔问题的结果,即i个盘子通过两个中转柱移动到4号柱需要多少步。

    则,F[i] = min{2*F[j]+H[i-j]}(1<=i<=n;0<=j<=i)

    以上方程的复杂度为O(N^2),是比较低效的方法。那么,有没有更为优化的方法呢?

    答案是有的,我们可以做到O(N),但是没有用。上述算法而言,我们都是要通过比较大小找出最小值的,且不论H[i]超不超int的问题,我们这题,每次%1000007后,我们根本无法保证找到的最小的就是最小的,因为有可能1000008%1000007<1000006%1000007,因为取模运算的存在。

    怎么办?找一个新的规律,f[i],表示i个盘子的四塔问题的解。我们通过求出f[i]的值,发现了一个新的规律:

    f[1] : 0 +2^0=1;
    f[2] : 1 +2^1=3;
    f[3] : 3 +2^1=5;
    f[4] : 5 +2^2=9;
    f[5] : 9 +2^2=13;
    f[6] : 13+2^2=17;
    f[7] : 17+2^3=25;
    f[8] : 25+2^3=33;
    f[9] : 33+2^3=41;
    f10] : 41+2^3=49;
    f[11]: 49+2^4=65;
    即,f[i]-f[i-1]的值是有规律的,1个2^0,2个2^1,3个2^2,4个2^3,5个2^4以此类推。所以很容易写出代码,于是这题就这么迎刃而解了。

    #include<cstdio>
    using namespace std;
    long long n,k,v,ans,mo=1e6+7;
    int main()
    {
        scanf("%lld",&n);
        k=1;
        v=1;
        for(k=1,v=1;n>k;)
        {
          n-=k;
          k++;
          v=(v+v)%mo;
          ans=(ans+k*v)%mo;
        }
        printf("%lld",(ans+n*v)%mo);
        return 0;
    }
    
  • 相关阅读:
    Java面向对象之继承
    ios Block解决循环引用和回传值
    iOS 计算label的高度
    十六进制的颜色
    App调SDK时加判断
    vmware中clone后的工作
    关于python保留几位小数,不进行四舍五入的方法
    git 绑定github
    opensuse ./filezilla: error while loading shared libraries: libpng12.so.0: cannot open shared object file: No such file or directory
    关于opensuse开机登录背景修改后,不生效的问题
  • 原文地址:https://www.cnblogs.com/yanshannan/p/7327916.html
Copyright © 2011-2022 走看看