• UVA 1358


    UVA 1358 - Generator

    题目链接

    题意:有m种字符(从'A'開始往后数的大写字母),如今有一个字符串,长度不超过12。如今每次随机生成一个字母,要求能产生该字符串的期望长度

    思路:dp[i]表示产生长度i的期望长度,那么每次产生一个字符。相应m种转移,每种转移的概率为1/m,转移后的长度能够利用KMP的next数组去高速获得,然后因为转移可能形成环的情况,所以无法直接DP,利用高斯消元去解方程组

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    typedef long long type;
    
    struct Frac {
    
        type a, b;
    
        Frac() {a = 0; b = 1;}
        Frac(type a, type b) {this->a = a; this->b = b; deal();}
    
        void init() {a = 0; b = 1;}
    
        type gcd(type a, type b) {
    	while (b) {
    	    type tmp = a % b;
    	    a = b;
    	    b = tmp;
    	}
    	return a;
        }
    
        void deal() {
    	type d = gcd(a, b);
    	a /= d; b /= d;
    	if (b < 0) {
    	    a = -a;
    	    b = -b;
    	}
        }
    
        Frac operator + (Frac c) {
    	Frac ans;
    	ans.a = a * c.b + b * c.a;
    	ans.b = b * c.b;
    	ans.deal();
    	return ans;
        }
    
        Frac operator - (Frac c) {
    	Frac ans;
    	ans.a = a * c.b - b * c.a;
    	ans.b = b * c.b;
    	ans.deal();
    	return ans;
        }
    
        Frac operator * (Frac c) {
    	Frac ans;
    	ans.a = a * c.a;
    	ans.b = b * c.b;
    	ans.deal();
    	return ans;
        }
    
        Frac operator / (Frac c) {
    	Frac ans;
    	ans.a = a * c.b;
    	ans.b = b * c.a;
    	ans.deal();
    	return ans;
        }
    
        void operator += (Frac c) {*this = *this + c;}
        void operator += (type c) {*this = *this + Frac(c, 1);}
        void operator -= (Frac c) {*this = *this - c;}
        void operator *= (Frac c) {*this = *this * c;}
        void operator /= (Frac c) {*this = *this / c;}
    
        bool operator > (Frac c) {return a * c.b > b * c.a;}
        bool operator == (Frac c) { return a * c.b == b * c.a;}
        bool operator < (Frac c) {return !(*this < c && *this == c);}
        bool operator >= (Frac c) {return !(*this < c);}
        bool operator <= (Frac c) {return !(*this > c);}
        
        bool operator != (Frac c) {return !(*this == c);}
        bool operator != (type c) {return *this != Frac(c, 1);}
    
        void operator = (type c) {this->a = c; this->b = 1;}
    };
    
    typedef long long ll;
    
    Frac A[15][15];
    
    int t, m, n, next[15];
    char str[15];
    
    void getnext() {
        next[0] = next[1] = 0;
        int j = 0;
        for (int i = 2; i <= n; i++) {
    	while (j && str[i] != str[j + 1]) j = next[j];
    	if (str[i] == str[j + 1]) j++;
    	next[i] = j;
        }
    }
    
    void build() {
        for (int i = 0; i <= n; i++)
    	for (int j = 0; j <= n + 1; j++)
    	    A[i][j].init();
        getnext();
        A[n][n] = 1;
        for (int i = 0; i < n; i++) {
    	A[i][i] = 1;
    	A[i][n + 1] = 1;
    	for (int j = 0; j < m; j++) {
    	    if (str[i + 1] == j + 'A')
    		A[i][i + 1] += Frac(-1, m);
    	    else {
    		int tmp = i;
    		int flag = 1;
    		while (tmp) {
    		    tmp = next[tmp];
    		    if (str[tmp + 1] == j + 'A') {
    			flag = 0;
    			A[i][tmp + 1] += Frac(-1, m);
    			break;
    		    }
    		}
    		if (flag) A[i][0] += Frac(-1, m);
    	    }
    	}
        }
    }
    
    ll gauss() {
        for (int i = 0; i <= n; i++) {
    	int r;
    	for (r = i; r <= n; r++)
    	    if (A[r][i] != 0) break;
    	for (int j = i; j <= n + 1; j++)
    	    swap(A[i][j], A[r][j]);
    	for (int j = n + 1; j > i; j--)
    	    A[i][j] /= A[i][i];
    	A[i][i] = 1;
    	for (int j = 0; j <= n; j++) {
    	    if (i == j) continue;
    	    if (A[j][i] != 0) {
    		for (int k = n + 1; k > i; k--)
    		    A[j][k] -= A[j][i] * A[i][k];
    		A[j][i] = 0;
    	    }
    	}
        }
        return (A[0][n + 1] / A[0][0]).a;
    }
    
    int main() {
        int cas = 0;
        scanf("%d", &t);
        while (t--) {
    	scanf("%d%s", &m, str + 1);
    	n = strlen(str + 1);
    	build();
    	printf("Case %d:
    ", ++cas);
    	printf("%lld
    ", gauss());
    	if (t) printf("
    ");
        }
        return 0;
    }


    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    排序算法 之 冒泡排序 插入排序 希尔排序 堆排序
    DataStructure之线性表以及其实现
    使用可重入函数进行更安全的信号处理
    内存经济学
    电脑通用技能
    循环套餐的逻辑
    占用了多少内存
    索引的用法
    电脑的眼缘
    字符串积木
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4793630.html
Copyright © 2020-2023  润新知