• 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]歌唱王国
  • 相关阅读:
    yepnope.js 异步加载资源文件
    省心选房5步走 买房前先算经济账还要多打听
    css中inline、block、inlineblock的区别
    web标准化设计:常用的CSS命名规则
    用css的手段解决Google Chrome浏览器的字体最小12px问题
    HTML元素的默认样式
    CSS中 常见中文字体的英文名称
    《重构 改善既有代码的设计》书摘
    手机号码匹配规则
    WEB开发——大批量数据导出经验谈
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14091982.html
Copyright © 2020-2023  润新知