zoukankan      html  css  js  c++  java
  • Blocks_DP&&矩阵快速幂

    参考资料:http://www.tuicool.com/articles/beiyAv

    【题意】有n块砖。现要将砖全部染上红、蓝、绿、黄四种颜色。要求被染成红色和绿色的砖块数量必须为偶数,问一共有多少种染色方案。(由于答案较大,模10007)

    【思路】采用dp,然后转化为矩阵。

    dp:

    用dp[N][4]来表示N块砖块的染色情况,一共有四种状态。

    1.  dp[N][0] :表示N块中红色绿色的数量均为偶数。

    2. dp[N][1] :表示N块中红色为偶数,绿色为奇数。

    3. dp[N][2] :表示N块中红色为奇数,绿色为偶数。

    4. dp[N][3] :表示N块中红色绿色的数量均为奇数。

     而状态转移方程为:

    dp[N+1][0] = 2 * dp[N][0] + 1 * dp[N][1] + 1 * dp[N][2] + 0 * dp[N][3]

    dp[N+1][1] = 1 * dp[N][0] + 2 * dp[N][1] + 0 * dp[N][2] + 1 * dp[N][3]

    dp[N+1][2] = 1 * dp[N][0] + 0 * dp[N][1] + 2 * dp[N][2] + 1 * dp[N][3]

    dp[N+1][3] = 0 * dp[N][0] + 1 * dp[N][1] + 1 * dp[N][2] + 2 * dp[N][3]

    上述的转移方程可以转化为矩阵:

    |2 1 1 0|

    |1 2 0 1|

    |1 0 2 1|

    |0 1 1 2|

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    const int N=5;
    const int mod=10007;
    struct Mat
    {
        int n,m;
        long long int mat[N][N];
        void clear()
        {
            n=m=0;
            memset(mat,0,sizeof(mat));
        }
    };
    Mat mul(Mat a,Mat b)
    {
        Mat c;
        c.clear();
        c.n=a.n;c.m=b.m;
        for(int i=0;i<=a.n;i++)
        {
            for(int k=0;k<=a.n;k++)
            {
                if(a.mat[i][k])
                {
                    for(int j=0;j<=a.n;j++)
                    {
                        c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
                        c.mat[i][j]%=mod;
                    }
                }
            }
        }
        return c;
    }
    Mat pow(Mat a,int k)
    {
        Mat c;
        c.clear();
        c.n=c.m=4;
        for(int i=0;i<4;i++) c.mat[i][i]=1;
        while(k)
        {
            if(k&1) c=mul(c,a);
            k>>=1;
            a=mul(a,a);
        }
        return c;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        Mat a;
        a.clear();
        a.n=a.m=4;
        a.mat[0][0]=2;a.mat[0][1]=1;a.mat[0][2]=1;a.mat[0][3]=0;
        a.mat[1][0]=1;a.mat[1][1]=2;a.mat[1][2]=0;a.mat[1][3]=1;
        a.mat[2][0]=1;a.mat[2][1]=0;a.mat[2][2]=2;a.mat[2][3]=1;
        a.mat[3][0]=0;a.mat[3][1]=1;a.mat[3][2]=1;a.mat[3][3]=2;
        while(t--)
        {
            int n;
            scanf("%d",&n);
            Mat ans=pow(a,n);
            printf("%d
    ",ans.mat[0][0]);
        }
        return 0;
    }
  • 相关阅读:
    初学Android: 四大组件之Activity
    jQuery Pagination Plugin ajax分页控件
    PHPExcel 多工作表 导入
    PHPExcel 多工作表 导出
    js常用方法
    如何让多个不同版本的jquery库共存
    总结机器学习部分计算原理—续
    第四周学习进度报告
    总结机器学习部分计算原理
    数据清洗报告
  • 原文地址:https://www.cnblogs.com/iwantstrong/p/5976951.html
Copyright © 2011-2022 走看看