zoukankan      html  css  js  c++  java
  • loj#2128. 「HAOI2015」数字串拆分 矩阵乘法


    目录

    题目链接

    loj#2128. 「HAOI2015」数字串拆分

    题解

    (f(s))对于(f(i) = sum_{j = i - m}^{i - 1}f(j))
    这个可以用转移矩阵通过矩阵乘法处理出来
    预处理出(A[i][j])表示数S为(j * 10 ^ i)的转移矩阵
    对于g的转移
    (g(i) = sum_{j = 0}^{i - 1}g(j) * D(j + 1,i))
    D[i][j]表示第i位到底j位构成的数的f,(转移矩阵
    对于g的转移也是需要矩阵的
    g(0) = 1也就是{0,0,0,.....,0,1}

    代码

    
    #include<map> 
    #include<vector> 
    #include<cstdio> 
    #include<cstring> 
    #include<algorithm> 
    #define gc getchar()
    #define pc putchar 
    #define LL long long
    inline int read() { 
    	int x = 0,f = 1; 
    	char c = gc; 
    	while(c < '0' || c > '9')c = gc; 
    	while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = gc; 
    	return x * f; 
    } 
    void print(int x) { 
    	if(x < 0) { 
    		pc('-'); 
    		x = -x; 
    	} 
    	if(x >= 10) print(x / 10); 
    	pc(x % 10 + '0'); 
    } 
    const int maxn = 507; 
    int n,m; 
    const int mod = 998244353; 
    struct Ma { 
    	int a[6][6]; 
    	Ma() { memset(a,0,sizeof a); } 
    	Ma operator * (const Ma & t)const { 
    		Ma ret; 
    		memset(ret.a,0,sizeof ret.a); 
    		for(int i = 1;i <= m;++ i) 
    			for(int j = 1;j <= m;++ j) 
    				for(int k = 1;k <= m;++ k) 
    					(ret.a[i][j] += 1ll * a[i][k] * t.a[k][j] % mod) %= mod; 
    		return ret; 
    	} 
    	Ma operator + (const Ma &k)const { 
    		Ma ret; 
    		memset(ret.a,0,sizeof ret.a); 
    		for(int i = 1;i <= m;++ i) 
    			for(int j = 1;j <= m;++ j) 
    				ret.a[i][j] = (a[i][j] + k.a[i][j]) % mod; 
    		return ret; 
    	} 
    } A[maxn][10],f[maxn]; 
    char s[maxn];  
    int main() { 
    	scanf("%s",s + 1); 
    	n = strlen(s + 1); 
    	m = read(); 
    	for(int i = 1;i <= m;++ i) 
    		A[0][0].a[i][i] = 1 , 
    		A[0][1].a[i][m] = 1; 
    	for(int i = 1;i < m;++ i) 
    		A[0][1].a[i + 1][i] = 1; 
    	for(int i = 2;i <= 9;++ i) 
    		A[0][i] = A[0][i - 1] * A[0][1]; 
    	 for(int i = 1;i <= n;++ i) { //十进制快速幂 
    	 	A[i][0] = A[0][0]; 
    	 	A[i][1] = A[i - 1][9] * A[i - 1][1]; 
    	 	for(int j = 2;j <= 9;++ j) 
    	 		A[i][j] = A[i][j - 1] * A[i][1]; 
    	 } 
    	f[0].a[1][m] = 1; 
    	Ma now; 
    	for(int i = 1;i <= n;++ i) { 
    		now = A[0] [s[i] - '0']; 
    		for(int j = i - 1;j >= 0;-- j) { 
    			f[i] = f[i] + (f[j] * now);  
    			if(j) now = A[i - j][s[j] - '0'] * now; 
    		} 
    	}  
    	print(f[n].a[1][m]); 
    	pc('
    '); 
    	return 0; 
    } 
    
  • 相关阅读:
    java环境变量的搭建,《ecpilse,jdk》的下载
    Android Studio的下载和环境变量的配置
    微信小程序开发者工具包(官方版)
    Activity详解生命周期(Android)
    Android环境变量配置
    Android基础测试题(四)
    Android基础测试题(二)
    手机上实现细线的效果
    前端面试题
    js判断当前浏览器是pc端还是移动端
  • 原文地址:https://www.cnblogs.com/sssy/p/9682411.html
Copyright © 2011-2022 走看看