Luogu4548 CTSC2006 歌唱王国 概率生成函数、哈希

传送门


orz ymd

考虑构造生成函数:设\(F(x) = \sum\limits_{i=0}^\infty f_ix^i\),其中\(f_i\)表示答案为\(i\)的概率;又设\(G(x) = \sum\limits_{i=0}^\infty g_ix^i\),其中\(g_i\)表示经过了\(i\)步之后还没有结束的概率。那么答案显然是\(F'(1)\)

考虑在还没有结束的序列之后加入一个字符,那么有可能结束也有可能没有结束,即\(F(x) + G(x) = xG(x) + 1\)

两边求导并将\(x=1\)代入可以得到\(F'(1) = G(1)\)

接下来考虑在还没有结束的序列之后加入当前需要匹配的字符串,那么一定会结束,但有可能已经存在一个前缀满足条件。设\(a_i\)表示原字符串是否有长度为\(i\)的border,那么不难得到\(G(x)(\frac{x}{n})^m = \sum\limits_{i=1}^m a_iF(i)(\frac{x}{n})^{m-i}\)

\(x=1\)代入可以得到\(G(1) = \sum\limits_{i=1}^m a_in^i\)

那么使用哈希或者KMP求出所有的\(a_i\)即可求出答案。

#include<bits/stdc++.h>
//this code is written by Itst
using namespace std;

int read(){
    int a = 0; char c = getchar();
    while(!isdigit(c)) c = getchar();
    while(isdigit(c)){
        a = a * 10 + c - 48; c = getchar();
    }
    return a;
}

#define int long long
const int _ = 1e5 + 7;
const int seed = 2344259 , MOD = 134093753;
int powsd[_] , N , T , M;

namespace Hashing{
    int val[_];

    void init(int len){
        for(int i = 1 ; i <= len ; ++i)
            val[i] = (1ll * val[i - 1] * seed + read()) % MOD;
    }

    int qry(int l , int r){return (val[r] - val[l - 1] * powsd[r - l + 1] % MOD + MOD) % MOD;}
}

signed main(){
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    freopen("out","w",stdout);
#endif
    powsd[0] = 1; powsd[1] = seed;
    for(int i = 2 ; i <= 1e5 ; ++i)
        powsd[i] = 1ll * powsd[i - 1] * seed % MOD;
    N = read() % 10000; T = read();
    for(int i = 1 ; i <= T ; ++i){
        int L = read() , sum = 0 , tms = N; Hashing::init(L);
        for(int j = 1 ; j <= L ; ++j , tms = tms * N % 10000)
            if(Hashing::qry(1 , j) == Hashing::qry(L - j + 1 , L))
                sum = (sum + tms) % 10000;
        printf("%04lld\n" , sum);
    }
    return 0;
}

转载于:https://www.cnblogs.com/Itst/p/11089724.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值