【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;
}
原文地址:https://www.cnblogs.com/ivorysi/p/9543174.html