zoukankan      html  css  js  c++  java
  • LG P4548 [CTSC2006]歌唱王国

    Description

    在歌唱王国,所有人的名字都是一个非空的仅包含整数 $1sim n$ 的字符串。

    王国里生活着一大群咕噜兵,他们靠不停地歌唱首领——牛人酋长们的名字来获取力量。咕噜兵每一次歌唱过程是这样的:首先,他从整数生成器那儿获得一个数字,然后花一个时间单位将此数字唱出来,如果他发现某个牛人酋长的名字已经被歌唱出来(即此名字是歌唱序列的一个连续子串),那么这次歌唱过程就立即结束。

    相关名词定义:

    - 歌唱序列:如果某人歌唱了 $x$ 个数字,第 $i$ 次歌唱的数字为 $a_i$,那么歌唱序列 $=(a_1,a_2,cdots,a_x)$。
    - 整数生成器:歌唱王国的神物,它有一个按钮,如果你按一下按钮,将从 $1sim n$ 数字中等概率的随机返回一个整数。
    - 歌唱时间:在一次歌唱过程中花费的时间。

    歌唱时间是随机的,无法预料;不过歌唱时间的期望值是固定的,此期望值即平均来说歌唱时间有多长,亦可称作平均歌唱时间。

    王国里的人非常喜欢歌唱,他们希望歌唱的时间越长越好,所以他们决定罢免一些牛人酋长,使得平均歌唱时间变长。但是他们不能罢免掉所有的牛人酋长,否则他们每次歌唱都无法停止,无法获取力量;于是他们决定只保留一个牛人酋长而罢免其余的牛人酋长。

    你的任务是:对于给定的 $n$、牛人酋长的个数 $t$ 以及每一个牛人酋长的名字,告诉王国里的人们,对于 $1leq ileq t$,如果保留第 $i$ 个牛人酋长,罢免掉其余的,那么平均歌唱时间将是多少。

    提示:此数为一个非负整数!

    输出要求:由于这个数字太大,所以你只需输出这个数的末 $4$ 位数字。如果不足 $4$ 位,则前面补 $0$

    Solution

    设$f_x$为长度为$x$时成功匹配的概率,$g_x$为长度为$x$时尚未成功匹配的概率

    写出$f$的概率生成函数

    $$F(x)=sum_{i=0}^{+ infty} P_i x_i$$

    同样的写出$g$的

    发现$F(1)=1,F'(1)=E(x),F(x)+G(x)=G(x)x+1$

    上式的意义类似于DP转移

    还有一关系式,设$m$为字符集大小,$l$为字符串长度,$a$是该位是否为border的布尔数组

    $$left ( frac{1}{m} ight ) ^lg_x =sum _{i=1}^l a_ileft ( frac{1}{m} ight )^{l-i}f_{x+i} $$

    考虑在没有完成匹配的字符串后面接一个随机出一个原串的概率,右半部分是有可能产生原串的border导致提前匹配

    写成生成函数的形式

    $$left ( frac{x}{m} ight ) ^lG(x) =F(x)sum _{i=1}^l a_i left ( frac{x}{m} ight ) ^{l-i}$$

    对一式求导得

    $$F'(x)+G'(x)=xG'(x)+G(x)$$

    移项得

    $$F'(x)=(x-1)G'(x)+G(x)$$

    将$1$代入$x$

    $$F'(1)=G(1)=E(x)$$

    这非常屌,再搞另一个式子,已经知道要算$G(1)$,所以也代入$1$

    $$G(1)=sum_{i=1}^l a_im^i$$

    KMP或者hash胡搞,$O(l)$求解

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,t,m;
    bool a[100005];
    unsigned long long b[100005]={1},str[100005],has[100005],pn[100005]={1},ans;
    const unsigned long long mod=10000,base=1e9+7;
    inline int read()
    {
        int f=1,w=0;
        char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
        return f*w;
    }
    int main()
    {
        n=read(),t=read();
        for(int i=1;i<=100000;i++) b[i]=b[i-1]*base;
        for(int i=1;i<=100000;i++) pn[i]=pn[i-1]*n%mod;
        for(;t;t--)
        {
            m=read(),ans=0;
            for(int i=1;i<=m;i++) str[i]=read(),has[i]=has[i-1]*base+str[i];
            for(int i=1;i<=m;i++) a[i]=(has[i]==has[m]-has[m-i]*b[i]);
            for(int i=1;i<=m;i++) (ans+=a[i]*pn[i]%mod)%=mod;
            if(ans<1000) printf("0");
            if(ans<100) printf("0");
            if(ans<10) printf("0");
            printf("%d
    ",ans);
        }
        return 0;
    }
    [CTSC2006]歌唱王国
  • 相关阅读:
    Python 学习日记 第七天
    Python 学习日记 第六天
    Python 学习日记 第五天
    Python 学习日记 第四天
    Redis 中的数据类型及基本操作
    Asp.net mvc 中View 的呈现(二)
    Asp.net mvc 中View的呈现(一)
    Asp.net mvc 中Action 方法的执行(三)
    Asp.net mvc 中Action 方法的执行(二)
    Asp.net mvc 中Action 方法的执行(一)
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14091982.html
Copyright © 2011-2022 走看看