• 【LOJ】#3098. 「SNOI2019」纸牌


    LOJ#3098. 「SNOI2019」纸牌

    显然选三个以上的连续牌可以把他们拆分成三个三张相等的

    于是可以压((j,k))为有(j)个连续两个的,有(k)个连续一个的

    如果当前有(i)张牌,且(i >= j + k)

    那么可以((j,k) ightarrow (k,(i - j - k) \% 3))

    可以用矩阵乘法优化,每遇到一个有下限的牌面的就再特殊造一个矩阵转移

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define ba 47
    #define MAXN 5005
    //#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 = 998244353;
    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;
    }
    void update(int &x,int y) {
        x = inc(x,y);
    }
    int getid(int x,int y) {
        return x * 3 + y;
    }
    struct Matrix {
        int f[9][9];
        Matrix() {memset(f,0,sizeof(f));}
        friend Matrix operator * (const Matrix &a,const Matrix &b) {
    	Matrix c;
    	for(int k = 0 ; k < 9 ; ++k) {
    	    for(int i = 0 ; i < 9 ; ++i) {
    		for(int j = 0 ; j < 9 ; ++j) {
    		    update(c.f[i][j],mul(a.f[i][k],b.f[k][j]));
    		}
    	    }
    	}
    	return c;
        }
        friend Matrix fpow(Matrix a,int64 c) {
    	Matrix res,t = a;
    	for(int i = 0 ; i < 9 ; ++i) res.f[i][i] = 1;
    	while(c) {
    	    if(c & 1) res = res * t;
    	    t = t * t;
    	    c >>= 1;
    	}
    	return res;
        }
    }a,ans,b;
    int64 n;
    int C,X;
    void Solve() {
        read(n);read(C);
        for(int i = 0 ; i <= C ; ++i) {
    	for(int j = 0 ; j < 3 ; ++j) {
    	    for(int k = 0 ; k < 3 ; ++k) {
    		if(i < j + k) continue;
    		update(a.f[getid(j,k)][getid(k,(i - j - k) % 3)],1);
    	    }
    	}
        }
        for(int i = 0 ; i < 9 ; ++i) ans.f[i][i] = 1;
        read(X);
        int64 k;int t;
        int64 p = 0;
        for(int i = 1 ; i <= X ; ++i) {
    	read(k);read(t);
    	ans = ans * fpow(a,k - 1 - p);
    	memset(b.f,0,sizeof(b.f));
    	for(int h = t ; h <= C ; ++h) {
    	    for(int j = 0 ; j < 3 ; ++j) {
    		for(int k = 0 ; k < 3 ; ++k) {
    		    if(h < j + k) continue;
    		    update(b.f[getid(j,k)][getid(k,(h - j - k) % 3)],1);
    		}
    	    }
    	}
    	ans = ans * b;
    	p = k;
        }
        if(p < n) ans = ans * fpow(a,n - p);
        out(ans.f[0][0]);enter;
    }
    int main(){
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    
  • 相关阅读:
    android中statusbar高度的问题
    int和short做循环计数器时的效率问题
    解决Rectangle Packing问题【原创】
    10个android开源项目(转)
    自动编译.9.png文件
    通过wifi调试android程序
    HBase 性能优化笔记
    [转载]定制CentOS 6.3 自动安装盘
    region split时metascan出现regioninfo为空
    Google Dremel 原理 如何能3秒分析1PB
  • 原文地址:https://www.cnblogs.com/ivorysi/p/11015058.html
Copyright © 2020-2023  润新知