• GDCPC2021 E


    题目

    source

    题解

    一眼看出是kmp+数位dp,然后就掉坑里了。。。
    数位dp显然时间会爆。观察数据范围,发现k长度最多为5,加上mod11的11个余数,最多有55个状态,可以使用矩阵快速幂。
    假设(f_{i,j})代表余数为i,当前匹配位置为j的结果。任意写出递推式,直接套矩阵快速幂。初始只有(f_{0,1}=1)(匹配状态从1开始),最终n次幂后将(f_{i,len+1})(f_{0,i})全部加起来就是答案了。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 500 + 10;
    const int M = 998244353;
    typedef long long ll;
    #define endl '
    '
    typedef long long ll;
    
    struct mat {
    	ll arr[N][N];
    	int n;
    	mat(const ll mx[N][N], int n) : n(n) {
    		for(int i = 1; i <= n; i++) {
    			for(int j = 1; j <= n; j++) {
    				arr[i][j] = mx[i][j];
    			}
    		}
    	}
    	mat(int n) : n(n){
    		for(int i = 1; i <= n; i++) {
    			for(int j = 1; j <= n; j++) {
    				arr[i][j] = 0;
    			}
    		}
    	}
    	mat(const mat& m) : mat(m.arr, m.n){}
    	mat operator * (const mat &rhs) const {
    		ll res[N][N];
    		for(int i = 1; i <= n; i++) {
    			for(int j = 1; j <= n; j++) {
    				ll sum = 0;
    				for(int k = 1; k <= n; k++) {
    					sum += arr[i][k] * rhs.arr[k][j] % M;
    					sum %= M;
    				}
    				res[i][j] = sum;
    			}
    			
    		}
    		return mat(res, n);
    	}
    };
    
    int di[20];
    int nt[20];
    ll ans[N];
    int len;
    
    void getnext() {
        int i = 1, j = 0;
        nt[i] = j;
        while(i <= len) {
            if(j == 0 || di[i] == di[j]) {
                i++;
                j++;
                nt[i] = j;
            } else {
                j = nt[j];
            }
        }
    }
    
    int id(int st, int mod) {
    	return mod * 7 + st;	
    }
    
    mat qpow(mat A, int b) {
    	mat res(100);
    	for(int i = 1; i <= res.n; i++) res.arr[i][i] = 1;
    	while(b) {
    		if(b & 1) {
    			res = res * A;
    		}
    		A = A * A;
    		b = (b >> 1);
    	}
    	return res;
    }
    
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(0), cout.tie(0);
    	int t;
    	cin >> t;
    	while(t--) {
    		int n, k;
    		cin >> n >> k;
    		len = 0;
    		bool flag = true;
    		do{
    			if(k > 10 && (k % 10)) flag = false;
    			else if(k < 10 && k != 1) flag = false;
    			di[++len] = k % 10;
    			k /= 10;
    		} while(k);
    		if(n + 1 < len) flag = false;
    		getnext();
    		mat A(100);
    		auto &arr = A.arr;
    		for(int i = 1; i <= len + 1; i++) {
    			for(int j = 0; j < 11; j++) {
    				int id2 = id(i, j);
    				for(int k = 0; k <= 9; k++) {
    					int st = i, mod = j;
    					if(st < len + 1) {
    						while(st && k != di[st]) {
    							st = nt[st];
    						}
    						st++;
    					}
    					mod = (mod * 10 + k) % 11;
    					int id1 = id(st, mod);
    					arr[id1][id2]++;
    				}
    			}
    		}
    		mat res(qpow(A, n));
    		int tar = id(1, 0);
    		for(int i = 1; i <= 100; i++) {
    			ans[i] = res.arr[i][tar];
    		}
    		ll tans = 0;
    		for(int i = 0; i < 11; i++) {
    			tans += ans[id(len + 1, i)];
    			tans %= M;
    		}
    		for(int i = 1; i <= len; i++ ) {
    			tans += ans[id(i, 0)];
    			tans %= M;
    		}
    		cout << (tans + flag) % M << endl;
    	}
    }
    
  • 相关阅读:
    java中static的用法
    java策略设计模式
    java模板设计模式
    Spring 学习笔记 8. 尚硅谷_佟刚_Spring_使用外部属性文件
    Spring 学习笔记 7. 尚硅谷_佟刚_Spring_Bean 的作用域
    Spring学习笔记 6. 尚硅谷_佟刚_Spring_Bean 之间的关系
    Spring学习笔记 5. 尚硅谷_佟刚_Spring_自动装配
    Spring 学习笔记 4. 尚硅谷_佟刚_Spring_属性配置细节
    Spring 学习笔记 3. 尚硅谷_佟刚_Spring_配置 Bean
    Spring 学习笔记 2. 尚硅谷_佟刚_Spring_IOC&DI概述
  • 原文地址:https://www.cnblogs.com/limil/p/14979260.html
Copyright © 2020-2023  润新知