zoukankan      html  css  js  c++  java
  • SGU 197.Nice Patterns Strike Back

    时间限制:0.5s

    空间限制:6M

    题意:

           给出长n(n<=10^100)和宽m(m<=5)的地面,铺上黑色和白色的地板,使得没有任意一个2*2大小的地面铺同种颜色的方案数是多少.

     

     

     

     

     

     

     

     

     

     

     

     

     


    Solution:

                 状态压缩,一个数字的对应为01分别代表铺白色和黑色地板,对于每一列有(1<<m)种状态.

                 我们可以构造一个矩阵,mat[i][j]代表,第一列是状态是i,第二列是j的方案数,显然mat[i][j]不是0就是1,而且很容易判断构造.

                 然后我们只要对这个矩阵进行快速幂运算,幂为(n-1),当然不要忘记取模,最后把mat所有元素加起来就是我们想要的答案了.

                 由于n比较大,所以要做大数的减一,和除以二的运算.

     

    code

    #include <iostream>
    #include <cstring>
    #include <string>
    using namespace std;
    struct Mat {
        int mat[100][100];
    } mx;
    int pow[109];
    int n, m, mod, len;
    Mat operator * (Mat a, Mat b) {
        Mat c;
        memset (c.mat, 0, sizeof c.mat);
        for (int k = 0; k <  (1 << m); k++)
            for (int i = 0; i <  (1 << m); i++)
                for (int j = 0; j <  (1 << m); j++)
                    (c.mat[i][j] += (a.mat[i][k] * b.mat[k][j]) % mod) %= mod;
        return c;
    
    }
    inline int div2() {
        int ans[103] = {0};
        int i, res = 0;
        for(i = 0; i < len; ++i) {
            ans[i] = (pow[i]+res*10)/2;
            res = (pow[i]+res*10)%2;
        }
        if(ans[0] == 0) len--;
        for(i = 0+(ans[0] == 0); i < len+(ans[0] == 0); i++)
            pow[i-(ans[0] == 0)] = ans[i];
        return res;
    }
    Mat operator ^ (Mat a, int pow[]) {
        Mat c;
        for (int i = 0; i <  (1 << m); i++)
            for (int j = 0; j <  (1 << m); j++)
                c.mat[i][j] = (i == j);
        while (len) {
            if (div2() )
                         c = c * a;
            a = a * a;
        }
        return c;
    }
    string s;
    int main() {
        ios::sync_with_stdio (0);
        while(cin >> s >> m >> mod){
        for (int i = 0; i < s.size(); ++i)
            pow[i] = s[i] - '0';
        len = s.size();
        for (int i = len - 1; i >= 0; i--) {
            if (pow[i]) {
                --pow[i];
                break;
            }
            else
                pow[i] = 9;
        }
        if (pow[0] == 0) {
            for (int i = 0; i < len - 1; i++) pow[i] = 9;
            pow[--len]=0;
        }
        for (int i = 0; i < (1 << m); i++)
            for (int j = 0; j < (1 << m); j++) {
                mx.mat[i][j] = 1;
                for (int k = 0, tem = i ^ j; k < m - 1; k++)
                    if (  (tem & 1 << k) == 0  && (tem & 1 << k + 1) == 0
    &&( ( (i & 1 << k) > 0 && (i & 1 << k + 1) > 0) || ( ( (i & 1 << k) == 0 && (i & 1 << k + 1) == 0) ) ) ) {
                        mx.mat[i][j] = 0;
                        break;
                    }
            }
        mx = mx ^ pow;
        int ans = 0;
        for (int i = 0; i < (1 << m); i++)
            for (int j = 0; j < (1 << m); j++) {
                ans += mx.mat[i][j];
                while (ans >= mod) ans -= mod;
            }
        cout << ans << endl;
        }
    }
    View Code

                 

  • 相关阅读:
    【题解】【BT】【Leetcode】Populating Next Right Pointers in Each Node
    【题解】【BT】【Leetcode】Binary Tree Level Order Traversal
    【题解】【BST】【Leetcode】Unique Binary Search Trees
    【题解】【矩阵】【回溯】【Leetcode】Rotate Image
    【题解】【排列组合】【素数】【Leetcode】Unique Paths
    【题解】【矩阵】【回溯】【Leetcode】Unique Paths II
    【题解】【BST】【Leetcode】Validate Binary Search Tree
    【题解】【BST】【Leetcode】Convert Sorted Array to Binary Search Tree
    第 10 章 判断用户是否登录
    第 8 章 动态管理资源结合自定义登录页面
  • 原文地址:https://www.cnblogs.com/keam37/p/4012789.html
Copyright © 2011-2022 走看看