zoukankan      html  css  js  c++  java
  • hdu 2842(矩阵高速幂+递推)

    题意:一个中国环的游戏,规则是一个木棒上有n个环。第一个环是能够任意放上或拆下的,剩下的环x假设想放上或拆下必须前一个环x-1是放上的且前x-2个环所有是拆下的,问n个环最少多少次操作能够所有拆掉。


    题解:须要进行递推,首先第一步肯定是要拆第n个环保证操作次数最少,由于后面的环是否存在对前面的环不造成影响,而先拆前面的假设要拆后面的环还是要把前面的放上,f(n)表示拆掉前n个环须要的最少操作次数,先拆第n个要拆前n-2个再拆第n个。花费f(n-2)+1,然后这时是00…0010。要拆第n-1个须要先把前n-2个放上,花费的步数和拆下是一样是f(n-2),这时就是11…1110,所有拆掉就是f(n-1),因此递推公式是f(n) = f(n-1) + 2 * f(n-2) + 1。

    最后矩阵高速幂即可了。

    #include <stdio.h>
    #include <string.h>
    const int MOD = 200907;
    struct Mat {
        long long g[3][3];
    }ori, res;
    long long n;
    
    Mat multiply(Mat x, Mat y) {
        Mat temp;
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++) {
                temp.g[i][j] = 0;
                for (int k = 0; k < 3; k++)
                    temp.g[i][j] = (temp.g[i][j] + x.g[i][k] * y.g[k][j]) % MOD;
            }
        return temp;
    }
    
    void calc(long long n) {
        while (n) {
            if (n & 1)
                ori = multiply(ori, res);
            n >>= 1;
            res = multiply(res, res);
        }
    }
    
    int main() {
        while (scanf("%lld", &n) == 1 && n) {
            if (n == 1 || n == 2) {
                printf("%lld
    ", n);
                continue;
            }
            memset(ori.g, 0, sizeof(ori.g));
            memset(res.g, 0, sizeof(res.g));
            ori.g[0][0] = 2;
            ori.g[0][1] = ori.g[0][2] = 1;
            res.g[0][0] = res.g[0][1] = res.g[2][0] = res.g[2][2] = 1;
            res.g[1][0] = 2;
            calc(n - 2);
            printf("%lld
    ", ori.g[0][0]);
        }
        return 0;
    }
  • 相关阅读:
    C++
    C语言获取系统时间的几种方式
    我在学习编程中犯的两个最大错误
    《十天学会单片机和C语言编程》
    socket 编程通信实例
    比尔·盖茨给年轻人的十一个忠告 句句是哲理
    程序员有八个级别。
    DOS debug 命令的详细用法
    从命令行模式运行Windows管理工具。
    无法删除DLL文件解决方法(转)
  • 原文地址:https://www.cnblogs.com/llguanli/p/8591543.html
Copyright © 2011-2022 走看看