• 【LOJ】#3123. 「CTS2019 | CTSC2019」重复


    LOJ3123

    60pts

    正难则反,熟练转成总方案数减掉每个片段都大于等于s的字典序的方案

    按照一般的套路建出kmp上每个点加一个字符的转移边的图(注意这个图开始字母必须是nxt链中下一个相邻的字符最大的一个,不然就字典序比它小了)

    然后大力猜结论可能是走m步走出一个环的个数,很容易发现这是不漏的,因为一个串无限重复最后都会走出一个m步的(不一定是简单环的)环

    不重的我没证出来,抱着试试看的心态我们写个极其简单的dp,发现它过了……

    100pts

    很容易发现每个点要么走到nxt链中下一个相邻字符中最大的一个,要么走到0

    我们对于一个环可以分成经过0的和不经过0的

    不经过0的从每个点开始走m步判断一下就可以

    经过0的可以通过枚举每个点走了几步没到0的边然后走了一步到0

    我们预处理出(f[i][j])表示走了i步到达j点,枚举初始走了几步相乘即可

    #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 MAXN 2005
    #define ba 47
    //#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 M,N,nxt[MAXN],to[MAXN][26],mx[MAXN];
    int dp[MAXN][MAXN];
    char s[MAXN];
    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 fpow(int x,int c) {
        int res = 1,t = x;
        while(c) {
    	if(c & 1) res = mul(res,t);
    	t = mul(t,t);
    	c >>= 1;
        }
        return res;
    }
    void Solve() {
        read(M);
        scanf("%s",s + 1);
        N = strlen(s + 1);
        for(int i = 2 ; i <= N ; ++i) {
    	int p = nxt[i - 1];
    	while(p && s[i] != s[p + 1]) p = nxt[p];
    	if(s[i] == s[p + 1]) nxt[i] = p + 1;
    	else nxt[i] = 0;
        }
        for(int i = 0 ; i <= N ; ++i) {
    	mx[i] = mx[nxt[i]];
    	if(i != N) mx[i] = max(mx[i],s[i + 1] - 'a');
    	for(int j = 0 ; j < mx[i] ; ++j) to[i][j] = -1;
    	for(int j = mx[i] ; j < 26 ; ++j) {
    	    if('a' + j == s[i + 1]) to[i][j] = i + 1;
    	    else {
    		int p = nxt[i];
    		while(to[p][j] == -1) p = nxt[p];
    		to[i][j] = to[p][j];
    	    }
    	}
        }
        int ans = 0;
        dp[0][0] = 1;
        for(int i = 0 ; i < M ; ++i) {
    	for(int j = 0 ; j <= N ; ++j) {
    	    if(!dp[i][j]) continue;
    	    for(int h = mx[j] ; h < 26 ; ++h) {
    		update(dp[i + 1][to[j][h]],dp[i][j]);
    	    }
    	}
        }
        for(int i = 0 ; i <= N ; ++i) {
    	int u = i;
    	for(int j = 0 ; j < M ; ++j) {
    	    update(ans,mul(25 - mx[u],dp[M - j - 1][i]));
    	    u = to[u][mx[u]];
    	}
    	if(u == i) update(ans,1);
        }
        out(inc(fpow(26,M),MOD - ans));enter;
    
    }
    
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    
    
  • 相关阅读:
    fedora29 安装mongodb 4.0,6问题记录
    乱花渐入迷人眼------从解决jqueryEasyUI上传插件提交ajax请求谈网页调试
    thinkphp5权限仿制
    基于tornado python pandas和bootstrap上传组件的mongodb数据添加工具
    tornado下pandas ndarray乱试
    一个tornado框架下的文件上传案例
    一例tornado框架下利用python panda对数据进行crud操作
    PHP 基础语法实例及注意事项
    转:github使用教程(重装系统后遇到问题该文章帮我解决了)
    ubuntu同步系统时间命令
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10929250.html
Copyright © 2020-2023  润新知