• Bzoj1009: [HNOI2008]GT考试


    题面

    传送门

    Sol

    (f[i][j])表示到第(i)个数,最后(j)个为不吉利数字的前缀的方案数
    于是就可以写一个(KMP)套暴力(DP)(next)转移

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    
    IL ll Read(){
        RG ll x = 0, z = 1; RG char c = getchar();
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
        return x * z;
    }
    
    int n, m, k, f[101010][30], nxt[30], ans;
    char s[30];
    
    int main(RG int argc, RG char* argv[]){
        n = Read(); m = Read(); k = Read();
        scanf(" %s", s + 1);
        for(RG int i = 2, j = 0; i <= m; ++i){
            while(j && s[i] != s[j + 1]) j = nxt[j];
            if(s[i] == s[j + 1]) nxt[i] = ++j;
        }
        f[0][0] = 1;
        for(RG int i = 1; i <= n; ++i)
            for(RG int j = 0; j < m; ++j){
                if(!f[i - 1][j]) continue;
                for(RG int l = '0'; l <= '9'; ++l){
                    RG int p = j;
                    while(p && l != s[p + 1]) p = nxt[p];
                    if(s[p + 1] == l) ++p;
                    f[i][p] = (f[i][p] + f[i - 1][j] % k) % k;
                }
            }
        for(RG int i = 0; i < m; ++i) ans = (ans + f[n][i]) % k;
        printf("%d
    ", ans);
        return 0;
    }
    
    

    我们发现转移是一样的,预处理出来,(n)这么大那就矩阵乘法优化一下

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    
    IL ll Read(){
        RG ll x = 0, z = 1; RG char c = getchar();
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
        return x * z;
    }
    
    int n, m, k, nxt[30], ans;
    char s[30];
    
    struct Matrix{
    	int a[30][30];
    
    	IL void Clear(){  Fill(a, 0);  }
    	
    	IL void Init(){  Clear(); for(RG int i = 0; i < m; ++i) a[i][i] = 1;  }
    
    	IL int* operator [](RG int x){  return a[x];  }
    
    	IL Matrix operator *(RG Matrix B){
    		RG Matrix C; C.Clear();
    		for(RG int i = 0; i < m; ++i)
    			for(RG int j = 0; j < m; ++j)
    				for(RG int l = 0; l < m; ++l)
    					(C[i][l] += (1LL * a[i][j] * B[j][l] % k)) %= k;
    		return C;
    	}
    } S, E;
    
    int main(RG int argc, RG char* argv[]){
        n = Read(); m = Read(); k = Read();
    	scanf(" %s", s + 1);
    	for(RG int i = 2, j = 0; i <= m; ++i){
    		while(j && s[i] != s[j + 1]) j = nxt[j];
    		if(s[i] == s[j + 1]) nxt[i] = ++j;
    	}
    	for(RG int i = 0; i < m; ++i)
    		for(RG int j = '0'; j <= '9'; ++j){
    			RG int p = i;
    			while(p && j != s[p + 1]) p = nxt[p];
    			if(s[p + 1] == j) ++p;
    			++E[i][p];
    		}
    	S[0][0] = 1;
    	for(RG int i = n; i; i >>= 1, E = E * E) if(i & 1) S = S * E;
    	for(RG int i = 0; i < m; ++i) ans = (ans + S[0][i]) % k;
    	printf("%d
    ", ans);
        return 0;
    }
    
    
  • 相关阅读:
    借助backtrace和demangle实现异常类Exception
    mysql数据库表里首行和末行的取得方法
    斐波那契高效算法(4种算法综合分析)
    sublime学习之--批量在多行首位加入代码
    Zabbix --&gt; client安装以及怎样加入数据库的动态监控视图
    sdut 3-6 静态数据成员与静态成员函数
    poj3411Paid Roads
    python中get pass用法
    Qt之QListWidget:项目的多选与单选设置
    Qt之QListWidget:项目的多选与单选设置
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8318154.html
Copyright © 2020-2023  润新知