zoukankan      html  css  js  c++  java
  • 【LOJ】#2075. 「JSOI2016」位运算

    题解

    压的状态是一个二进制位,我们规定1到n的数字互不相同是从小到大,二进制位记录的是每一位和后一个数是否相等,第n位记录第n个数和原串是否相等,处理出50个转移矩阵然后相乘,再快速幂即可

    代码

    #include <bits/stdc++.h>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mp make_pair
    #define MAXN 100005
    #define mo 99994711
    #define pb push_back
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') {
            res = res * 10 + c - '0';
            c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) out(x / 10);
        putchar('0' + x % 10);
    }
    const int MOD = 1000000007;
    int N,K;
    char s[55];
    int inc(int a,int b) {
        return a + b >= MOD ? a + b - MOD : a + b;
    }
    int mul(int a,int b) {
        return 1LL * a * b % MOD;
    }
    struct Matrix {
        int r,c,f[(1 << 7) + 5][(1 << 7) + 5];
        Matrix() {memset(f,0,sizeof(f));}
        friend Matrix operator * (const Matrix &a,const Matrix &b) {
            Matrix c;c.r = a.r;c.c = b.c;
            for(int i = 0 ; i <= a.r ; ++i) {
                for(int j = 0 ; j <= b.c ; ++j) {
                    for(int k = 0 ; k <= b.r ; ++k) {
                        c.f[i][j] = inc(c.f[i][j],mul(a.f[i][k],b.f[k][j]));
                    }
                }
            }
            return c;
        }
    }A,F,ans;
    void fpow(Matrix &res,Matrix &x,int c) {
        res = x;Matrix t = x;--c;
        while(c) {
            if(c & 1) res = res * t;
            t = t * t;
            c >>= 1;
        }
    }
    int state[1005],tot;
    void Solve() {
        read(N);read(K);
        scanf("%s",s + 1);
        int L = strlen(s + 1);
        for(int i = 0 ; i < (1 << N) ; ++i) {
            int t = 0,tmp = i;
            while(tmp) {t ^= (tmp & 1);tmp >>= 1;}
            if(!t) state[++tot] = i;
        }
        A.r = A.c = F.r = F.c = (1 << N) - 1;
        for(int i = 0 ; i <= A.r ; ++i) A.f[i][i] = 1;
        for(int i = 1 ; i <= L ; ++i) {
            memset(F.f,0,sizeof(F.f));
            for(int S = 0 ; S < (1 << N) ; ++S) {
                for(int j = 1 ; j <= tot ; ++j) {
                    int U = state[j] | ((s[i] - '0') << N),T = 0;
                    bool flag = 1;
                    for(int k = N ; k >= 1 ; --k) {
                        if((S >> (k - 1) & 1) && (U >> (k - 1) & 1) > (U >> k & 1)) {flag = 0;break;}
                    }
                    if(!flag) continue;
                    for(int k = N ; k >= 1 ; --k) {
                        int t = (S >> (k - 1) & 1) && ((U >> (k - 1) & 1) == (U >> k & 1));
                        T |= t << (k - 1);
                    }
                    F.f[S][T] = inc(F.f[S][T],1);
                }
            }
            A = A * F;
        }
        fpow(ans,A,K);
        out(ans.f[(1 << N) - 1][0]);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    
  • 相关阅读:
    Linux 性能监测:CPU
    Linux 性能监测:介绍
    数据库设计
    数据库设计
    如何将Virtualbox和VMware虚拟机相互转换
    如何将Virtualbox和VMware虚拟机相互转换
    stat()获得文件信息
    stat()获得文件信息
    网游创业为什么会失败?
    网游创业为什么会失败?
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9543174.html
Copyright © 2011-2022 走看看