zoukankan      html  css  js  c++  java
  • HDU2276——Kiki & Little Kiki 2

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2276

    题目意思:给予一个01字符串,表示一串灯的明亮状态,现在每过一秒,如何这个灯的左边的灯是亮的,我们就改变他的明亮状态。(从左往右依次更新)注:第一个的左边是最后一个(即0的左边是n-1),问n秒后所有灯的明亮状态。

    思路:采用矩阵快速幂啊!这个题十分有意思,采用了位运算,是真的没有想到。

    1 0 0 0 0 0 1
    1 1 0 0 0 0 0
    0 1 1 0 0 0 0
    0 0 1 1 0 0 0
    0 0 0 1 1 0 0
    0 0 0 0 1 1 0
    0 0 0 0 0 1 1

    以上是以样例一(0101111)为例的系数矩阵,我们发现对于相邻的两位只存在四种情况00,01,10,11,其中00,01保持原样不变,10和11分别变成11和10,我们惊奇的发现(1&1)^(1&1)=0,(1&1)^(1&0)=1,是不是满足这个变换?而(0&1)^(0&1)=0,(0&1)^(1&1)=1保持不变。这个就是这道题的难点,希望可以记住这个类型的变换。这样我们就可以通过上面的系数矩阵通过矩阵快速幂快速得到n秒后的状态了!!!

    代码:

    //Author: xiaowuga
    #include <bits/stdc++.h>
    #define maxx INT_MAX
    #define minn INT_MIN
    #define inf 0x3f3f3f3f
    #define maxn 101 
    using namespace std;
    typedef long long ll;
    int n;
    struct Matrix{
        ll mat[maxn][maxn];
        Matrix operator * (const Matrix & m) const{
            Matrix tmp;
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++){
                    tmp.mat[i][j]=0;
                    for(int k=0;k<n;k++){
                        tmp.mat[i][j]^=mat[i][k]&m.mat[k][j];
                    }
                }
            return tmp;
        }
    };
    Matrix POW(Matrix &m,ll k){
        Matrix ans;
        memset(ans.mat,0,sizeof(ans.mat));
        for(int i=0;i<n;i++) ans.mat[i][i]=1;
        while(k){
            if(k&1) ans=ans*m;
            k/=2;
            m=m*m;
        }
        return ans;
    }
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);
        ll num;
        while(cin>>num){
            string q;
            cin>>q;
            n=q.size();
            Matrix m,f;
            memset(m.mat,0,sizeof(m.mat));
            memset(f.mat,0,sizeof(f.mat));
            for(int i=0;i<n;i++) f.mat[i][0]=q[i]-'0';
            m.mat[0][0]=m.mat[0][n-1]=1;
            for(int i=1;i<n;i++) m.mat[i][i-1]=m.mat[i][i]=1;
            Matrix x=POW(m,num);
            Matrix ans=x*f;
            for(int i=0;i<n;i++) cout<<ans.mat[i][0];
            cout<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ZOJ 3332 Strange Country II
    ZOJ 3331 Process the Tasks(双塔DP)
    ZOJ 3326 An Awful Problem(模拟)
    HDU 1796 How many integers can you find(容斥原理)
    HDU 4059 The Boss on Mars(容斥原理)
    HDU 4135 Co-prime(容斥原理)
    HDU 5677 ztr loves substring(回文串加多重背包)
    CodeForces 668B Little Artem and Dance
    CodeForces 667A Pouring Rain
    Java实现 LeetCode 764 最大加号标志(暴力递推)
  • 原文地址:https://www.cnblogs.com/xiaowuga/p/7351857.html
Copyright © 2011-2022 走看看