zoukankan      html  css  js  c++  java
  • [HNOI2008]GT考试

    [HNOI2008]GT考试

    以前太菜, 一看到考试两字就劝退...

    题意: 求有多少字符集为数字, 长度为n的字符串, 要求字符串中不能出现特定字串

    不得不说这是一道字符串好题, 计数想(dp), (f_{i,j})表示长度为(i), 匹配到(j)位方案数. 转移方程较为复杂, 考虑到(f_{i,j})不止可以从(f_{i-1,j-1})转移过来, 因为失配时可以像(kmp)那样找到最长匹配前缀, 预处理出数组(g_{i,j})表示是否可以添加一个字符从匹配长度(i)到匹配长度(j). 这个(kmp)即可, 转移方程: (f_{i,j} = sum_{k=0}^{m-1}f_{i-1,k}*g_{k,j}) 像不像矩阵乘法, 没错它就是. 矩阵快速幂一发救星了

    (warning): 以下部分为本人(yy)

    突然想起了在图论中也有矩阵乘法维护走k步的方案数, 现在想想, 图论和动态规划好像有着某些联系, 我们可以把图论的边想象成动态规划的转移, 点化为状态, 这可能也是(floyd)可以解决最短路问题的本质吧

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    using namespace std;
    
    template <typename T>
    void read(T &x) {
        x = 0; bool f = 0;
        char c = getchar();
        for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
        for (;isdigit(c);c=getchar()) x=x*10+(c^48);
        if (f) x=-x;
    }
    
    template <typename T>
    void write(T x) {
        if (x < 0) putchar('-'), x = -x;
        if (x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    
    int n, m, P;
    
    const int N = 23;
    struct Matrix {
    	int f[N][N];
    	Matrix () {
    		memset(f, 0, sizeof(f));
    	}
    	Matrix operator * (Matrix y) {
    		Matrix tmp;
    		for (int i = 0;i < m; i++) 
    			for (int j = 0;j < m; j++) 
    				for (int k = 0;k < m; k++) 
    					tmp.f[i][j] = (tmp.f[i][j] + f[i][k] * y.f[k][j]) % P;
    		return tmp;
    	}
    }I, M;
    
    char s[N];
    
    int nxt[N];
    void prework() {
    	nxt[1] = 0; int j = 0;
    	for (int i = 2; i <= m; i++) {
    		while (j && s[j+1] != s[i]) j = nxt[j];
    		if (s[j+1] == s[i]) j++;
    		nxt[i] = j;
    	}
    	for (int i = 0;i < m; i++) {
    		for (int j = '0';j <= '9'; j++) {
    			int k = i;
    			while (k && s[k+1] != j) k = nxt[k];
    			if (s[k+1] == j) k++;
    			++M.f[i][k];
    		}
    	}
    }
    
    Matrix fpw(Matrix x, ll mi) {
    	Matrix res = I;
    	while (mi) {
    		if (mi & 1) res = res * x;
    		x = x * x;
    		mi >>= 1;
    	}
    	return res;
    }
    
    int main() {
    	read(n), read(m), read(P);
    	scanf ("%s", s + 1); prework();
    	for (int i = 0;i < m; i++) I.f[i][i] = 1;
    	Matrix ans = fpw(M, n);
    	ll res = 0;
    	for (int i = 0;i < m; i++) res += ans.f[0][i];
    	cout << res % P << endl;
    	return 0;
    }
    
  • 相关阅读:
    [Caffe] ubuntu14.04下使用OpenBLAS加速Caffe
    [CUDA] ubuntu14.04+cuda7.5下安装cudnn7.0
    ubuntu下virtualenv的复制
    SIFT特征学习笔记
    ubuntu14.04+opencv 3.0+python2.7安装及测试
    django之ORM
    django之路由(url)
    性能调优之MySQL篇四:MySQL配置定位以及优化
    性能调优之MySQL篇三:MySQL配置定位以及优化
    性能调优之MySQL篇二:MySQL配置文件My.ini配置文件优化
  • 原文地址:https://www.cnblogs.com/Hs-black/p/12238768.html
Copyright © 2011-2022 走看看